簡體   English   中英

輸入負數時,C程序中的模量返回錯誤量

[英]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;

地板師(Knuth)

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/ba%b的行為均未定義。 C11dr§6.5.56

**例外:

a%0的結果是不確定的。

對於2的補碼, INT_MIN % -1INT_MIN E% -1 (在數學上應為0)是問題。 這是由於INT_MIN / -1 (數學上應為INT_MAX + 1 )引起的,因為答案不適合int范圍。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM