負數

2012-07-30 61 views
115

在C程序中我試圖下面的操作模運算(只是爲了檢查的行爲)負數

x = 5 % (-3); 
y = (-5) % (3); 
z = (-5) % (-3); 

printf("%d ,%d ,%d", x, y, z); 

給我輸出作爲GCC (2, -2 , -2)。我每次都期待着一個積極的結果。模數可以爲負數嗎?任何人都可以解釋這種行爲嗎?

+0

可能的重複http://stackoverflow.com/questions/4003232/how-to-code-a-modulo-operator-in-cc-obj-c-that-handles-negative-numbers – james 2012-07-30 11:41:15

+1

可能重複的[模運算符與負值](http://stackoverflow.com/questions/7594508/modulo-operator-with-negative-values) – sugavaneshb 2015-02-08 08:46:18

回答

3

模操作的結果取決於分子的符號,因此你要-2 Ÿž

這裏的參考

http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_14.html

整數部門

本節介紹執行整數除法的功能。 這些函數在GNU C庫中是多餘的,因爲在GNU C中, '/'操作符總是向零調整。但在其他C 實現中,'/'可能會因負面參數而異。 div和ldiv非常有用,因爲它們指定如何將商數:朝零調整。其餘部分與 分子的符號相同。

+4

你指的是關於ANSI C的文本。這是一個相當古老的C規範。不是確定文本對於ANSI C是否正確,但絕對不適用於C99。在C99§6.5.5中,整數除法定義爲始終向零截斷。 – Palec 2014-02-05 20:36:49

+0

和一個鏈接:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf – 2015-05-05 21:25:20

102

C99 需要a/b可表示:

(a/b) * b+a%b應等於a

這是有道理的,在邏輯上。對不對?

讓我們來看看這導致:


例A. 5/(-3)-1

=>(-1) * (-3)+5%(-3) = 5

這隻能發生,如果5%(-3)是2.


實施例B.(-5)/3-1

=>(-1) * 3+(-5)%3 = -5

如果(-5)%3-2

+1

編譯器是否足夠聰明並檢測到無符號模另一個無符號總是正數?目前(當然,GCC 5.2)編譯器似乎認爲在這種情況下「%」返回「int」,而不是「無符號」,即使兩個操作數都是uint32_t或更大。 – 2016-09-24 14:56:47

+0

@FrederickNord你有一個例子來顯示[那個行爲](http://stackoverflow.com/questions/11720656/modulo-operation-with-negative-numbers#comment66655578_11720841)? – chux 2017-02-24 16:16:46

85

%操作者在C不在操作者這隻能發生但其餘運營商。

模數和餘數運算符在負值方面有所不同。

對於餘數運算符,結果的符號與被除數的符號相同,而使用模運算符時結果的符號與除數相同。

a % b定義爲%操作:

a == (a/b * b) + a % b 

/整數除法具有朝向0截斷。這是朝着0(而不是朝向負性無限性)完成的截斷,其將%定義爲餘數運算符而不是模運算符。

+4

[餘數爲模數運算的結果]由定義(https://en.wikipedia.org/wiki/Remainder)。應該沒有剩餘操作符這樣的事情,因爲沒有剩餘操作這樣的事情,所以稱爲模數。 – gronostaj 2015-06-27 20:49:16

+21

@gronostaj不在CS。查看像Haskell或Scheme這樣的更高級的語言,它們都定義了兩個不同的運算符(Scheme中的'remaining'和'modulo',Haskell中的'rem'和'mod')。這些運算符的規格在這些語言上的差異如何劃分:截斷爲0或朝向負無窮大。順便說一下,C標準決不會調用'*'模運算符*,他們只是將它命名爲*%運算符*。 – ouah 2015-12-21 16:55:44

+0

不要與在C'remainder' _function_,它實現IEEE其餘與混淆圓入,向最近的分割 – Eric 2017-09-18 02:11:48

44

基於C99的規格:a = (a/b) * b + a % b

我們可以寫一個函數來計算(a % b) = a - (a/b) * b

int remainder(int a, int b) 
{ 
    return a - (a/b) * b; 
} 

對於模運算,我們可以有下面的函數(假設B> 0)

int mod(int a, int b) 
{ 
    int r = a % b; 
    return r < 0 ? r + b : r; 
} 

我的結論是(A%B)中C是一個餘數運算符和NOT模運算符。

+1

此沒有給出陽性結果時,'B'是否定的(語義和實際上爲'r'和'b'都是負數,結果小於'-b')。爲了確保所有輸入的正面結果,你可以使用'r + abs(b)'或匹配'b's符號,你可以改變條件爲'r * b <0'。 – 2016-09-20 11:42:02

4

其他的答案已經在C99解釋或更高版本,涉及到負操作數整數的除法總是接近零截斷。

請注意,在C89中,向上或向下循環的結果是否是實現定義的。因爲在所有標準中(a/b) * b + a%b等於a,涉及負操作數的%的結果也在C89中實現定義。

23

我不認爲有任何需要檢查數字是否定的。 找到正模的最簡單的一般函數就是這個 - 它可以對x的正值和負值都有效。

int modulo(int x,int N){ 
    return (x % N + N) %N; 
} 
+0

這對我有用。謝謝!!! – 2017-12-18 01:05:38

3

在這些慣例源於數學的數學中,沒有斷言模數運算應該產生積極結果。

例如,

1 mod 5 = 1,但它也可以等於-4。也就是說,1/5產生從0開始的餘數1或從5開始產生-4。(兩個因子爲5)

類似地, -1模5 = -1,但它也可以等於4。 1/5從-5得到0或4的餘數-1。 (兩個因子爲5)

欲瞭解更多,請查看equivalence classes數學。

0

模數運算符就像mod運算符,當數字是正數時,但是如果數字是負數,則不同。

很多次在問題中,我們被要求以10^9 + 7的模數給出答案。

讓答案(在使用模之前)用'a'表示。

簡單直接的基於規則

如果a是,然後模10^9 + 7 = 一%(10^9 + 7)

如果是,則模10^9 + 7 = (一%(10^9 + 7))+(10^9 + 7)

如果在SUC h問題,我們發現循環的任何一步可能會計算出一個超出整數範圍的值(如果我們使用整數),那麼我們可以在該步驟中使用模運算符。最終答案就好像我們只使用模運算符一次。

這是因爲 - (a * b)%c =((a%c)(b%c))%c同樣適用於加法和減法。

1

模運算符給出餘數。在C 模運算符通常需要分子

  1. X = 5%(-3)的符號 - 在這裏分子是正的,因此它導致2
  2. Y =(-5)%(3) - 這裏分子是負的,因此它導致-2
  3. Z =(-5)%(-3) - 在這裏分子是負因此它導致-2

此外模數(餘數)操作者只能與使用整型,不能與浮點一起使用。

+0

如果您可以通過指向外部資源的鏈接來支持它,那就太好了。 – 2017-08-26 16:13:02

+0

https://archive.org/details/letusc_201605 – Kavya 2017-08-28 16:42:22