[c] 음수로 모듈로 연산

C 프로그램에서 나는 아래 작업을 시도하고 있었다 (동작을 확인하기 위해)

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

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

(2, -2 , -2)gcc에서 와 같이 출력을주었습니다 . 나는 매번 긍정적 인 결과를 기대하고있었습니다. 계수가 음수 일 수 있습니까? 아무도이 행동을 설명 할 수 있습니까?



답변

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


답변

%C 의 연산자는 모듈로 연산자가 아니라 나머지 연산자입니다.

모듈로 및 나머지 연산자는 음수 값이 다릅니다.

나머지 연산자의 경우 결과의 부호는 피제수의 부호와 같지만 모듈러스 연산자의 경우 결과의 부호는 제수와 같습니다.

C는 다음 과 같이 %작업을 정의합니다 a % b.

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

/향해 정수 나누기를 사용 0합니다. 그것은 모듈로 연산자가 아닌 나머지 연산자로 0정의하는 (음의 무한대가 아닌)쪽으로 수행되는 잘림입니다 %.


답변

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 % bC에서 나머지 연산이며 모듈로 연산 이 아니라는 것 입니다.


답변

나는 숫자가 음수인지 확인할 필요가 없다고 생각합니다.

포지티브 모듈로를 찾는 간단한 함수는 다음과 같습니다.

편집 : 가정 N > 0N + N - 1 <= INT_MAX

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

이것은 x의 양수과 음수모두에 적용 됩니다 .

원래 추신 : 또한 @chux가 가리키는 아웃으로, 귀하의 x와 N은 대체 각각 INT_MAX-1 및 INT_MAX 같은 도달 할 수있는 경우 intlong long int.

그리고 그들이 오랫동안 긴 한계를 넘어 서면 (즉, LLONG_MAX 근처), 당신은 여기에 다른 답변에서 설명 된 것처럼 긍정적이고 부정적인 경우를 별도로 처리해야합니다.


답변

다른 답변은 C99 이상 에서 설명 했으므로 음의 피연산자를 포함하는 정수 나누기는 항상 0으로 잘립니다 .

C89에서 , 결과가 상향 또는 하향으로 반올림되는지는 구현-정의 됨에 유의한다 . 모든 표준에서 (a/b) * b + a%b동일 하기 때문에 음의 피연산자가 포함 a된 결과 %도 C89에 구현 정의되어 있습니다.


답변

계수가 음수 일 수 있습니까?

%Euclidean_division 이후 가 아니라 나머지 연산자 인 나머지 나눗셈이므로 음수 일 수 있습니다 . C99이므로 결과는 0, 음수 또는 양수일 수 있습니다.

 // a % b
 7 %  3 -->  1
 7 % -3 -->  1
-7 %  3 --> -1
-7 % -3 --> -1  

모듈로 원 영업 이익은 고전적인 유클리드 모듈로 하지 %.

나는 매번 긍정적 인 결과를 기대하고있었습니다.

때마다 잘 정의 된 유클리드 모듈로 수행하려면 a/b정의를, a,b어떤 부호이며, 결과는 부정적인 결코 :

int modulo_Euclidean(int a, int b) {
  int m = a % b;
  if (m < 0) {
    // m += (b < 0) ? -b : b; // avoid this form: it is UB when b == INT_MIN
    m = (b < 0) ? m - b : m + b;
  }
  return m;
}

modulo_Euclidean( 7,  3) -->  1
modulo_Euclidean( 7, -3) -->  1
modulo_Euclidean(-7,  3) -->  2
modulo_Euclidean(-7, -3) -->  2   


답변

모듈로 연산의 결과는 분자의 부호에 따라 다르므로 yz에 대해 -2를 얻습니다.

여기 참조입니다

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

정수 부서

이 섹션에서는 정수 나누기를 수행하는 기능에 대해 설명합니다. GNU C에서는 ‘/’연산자가 항상 0으로 반올림하기 때문에 이러한 함수는 GNU C 라이브러리에서 중복됩니다. 그러나 다른 C 구현에서 ‘/’는 음수 인수로 다르게 반올림 될 수 있습니다. div와 ldiv는 몫을 반올림하는 방법을 지정하기 때문에 유용합니다. 나머지는 분자와 같은 부호를 갖습니다.