[英]modulus returning incorrect amount in c program when a negative number is entered
有人可以幫我找出為什么在此C程序中輸入負數時,該程序為何對模運算給出錯誤的答案嗎?
我很確定導致問題的原因是scanf
函數。 當使用正整數時,將給出正確的答案。
代碼如下:
#include <stdio.h>
int main()
{
int num1 = 0;
int num2 = 0;
int answer = 0;
puts("enter two number to find the modulus of...");
if (scanf("%3d %3d",&num1,&num2) != 2)
puts("something went wrong");
else {
answer = (num1 % num2);
printf("the modulus of %d and %d is: %d\n", num1, num2, answer);
}
}
在ANSI C中,沒有為負輸入定義模運算符結果的符號。 您可以從數學庫( ref )中嘗試div()
)。 它返回具有商和余數的結構,並且對於負輸入可靠地工作。
或者,正如Alexey Frunze所建議的那樣,您可以啟用C99模式。 我懶得查找標准,但是進行了一些測試( gcc -std=c99
)表明結果的符號與左側操作數的符號匹配。 因此,如果您想要ANSI兼容性, div()
仍然是最好的。
或者,您可以完全控制情況。 但是您必須選擇正確的方法。 以下是Wikipedia的內容 。
int x, y, q, r; // all snippets: left-arg, right-arg, quotient, remainder
q = trunc( (double)x / y);
r = x - y * q;
q = floor( (double)x / y);
r = x - y * q;
q = y > 0 ? floor( (double)x / y) : ceiling( (double)x / y);
r = x - y * q;
接受答案后
在C中,自C99起,即使使用負操作數也可以很好地定義%
的結果。 見下文。
在C中, %
運算符在C中被稱為“余數”,而不是“模數”。
要執行歐幾里得除法和余數而不會導致截斷,范圍, double
轉換問題**:
void Euclidean_divide_remainder(int a, int b, int *q, int *r) {
*q = a / b;
*r = a % b;
if (a < 0 && *r != 0) {
if (b < 0) { (*q)++; *r -= b; }
else { (*q)--; *r += b; }
}
}
void rtest(int a, int b) {
int eq, er;
Euclidean_divide_remainder(a, b, &eq, &er);
printf("f(%2d,%2d) / %2d %% %2d E/ %2d E%% %2d\n",
a, b, a / b, a % b, eq, er);
}
void rtest4(int a, int b) {
rtest(a, b);
rtest(a, -b);
rtest(-a, b);
rtest(-a, -b);
printf("\n");
}
int main(void) {
rtest4(7, 3);
return 0;
}
f( 7, 3) / 2 % 1 E/ 2 E% 1
f( 7,-3) / -2 % 1 E/ -2 E% 1
f(-7, 3) / -2 % -1 E/ -3 E% 2
f(-7,-3) / 2 % -1 E/ 3 E% 2
/運算符的結果是第一個操作數除以第二個的商。 %運算符的結果是余數 。 在這兩個操作中,如果第二個操作數的值為零,則行為是不確定的。 C11dr§6.5.55
當整數相除時,/運算符的結果是代數商,其中舍棄了任何小數部分。 (這通常稱為“向零截斷”。)如果商
a/b
是可表示的,則表達式(a/b)*b + a%b
等於a
; 否則,a/b
和a%b
的行為均未定義。 C11dr§6.5.56
**例外:
a%0
的結果是不確定的。
對於2的補碼, INT_MIN % -1
和INT_MIN E% -1
(在數學上應為0)是問題。 這是由於INT_MIN / -1
(數學上應為INT_MAX + 1
)引起的,因為答案不適合int
范圍。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.