code

C와 Python-모듈로 (%) 연산의 다른 동작

codestyles 2020. 11. 24. 08:01
반응형

C와 Python-모듈로 (%) 연산의 다른 동작


동일한 모드 작업이 사용되는 언어에 따라 다른 결과를 생성한다는 것을 발견했습니다.

Python에서 :

-1 % 10

9를 생성

C에서는 -1 을 생성합니다 !

  1. 어느 것이 올바른 모듈로입니까?
  2. C에서 mod 작업을 Python과 동일하게 만드는 방법은 무엇입니까?

  1. 두 변형 모두 정확하지만 수학 (특히 숫자 이론)에서는 Python의 모듈로 가 가장 일반적으로 사용됩니다.
  2. C에서는 ((n % M) + M) % MPython과 동일한 결과를 얻습니다. 예. ((-1 % 10) + 10) % 10. 양의 정수 : ((17 % 10) + 10) % 10 == 17 % 10및 C 구현의 두 변형 (양수 또는 음수 나머지)에 대해 여전히 작동하는 방식에 유의하십시오 .

파이썬에는 "진정한"모듈로 연산이 있고 C에는 나머지 연산이 있습니다.

음의 정수 나누기가 처리되는 방식, 즉 0 또는 마이너스 무한으로 반올림되는 방식과 직접적인 관계가 있습니다. 파이썬은 마이너스 무한으로 반올림하고 C (99)는 0으로 반올림하지만 두 언어 모두 (n/m)*m + n%m == n에서이므로 % 연산자는 올바른 방향으로 보상해야합니다.

Ada는 더 명시 적이며 as modrem.


C89 / 90에서 나눗셈 연산자와 음수 피연산자가있는 나머지 연산자의 동작은 구현 에 따라 정의됩니다 . 즉, 구현에 따라 두 동작 중 하나를 얻을 수 있습니다. 운영자가 서로 동의하면됩니다 : from a / b = qa % b = rfollows a = b * q + r. 결과에 비판적으로 의존하는 경우 코드에서 정적 어설 션을 사용하여 동작을 확인합니다.

C99에서는 관찰하는 동작이 표준이되었습니다.

사실, 두 행동 모두 특정 논리를 가지고 있습니다. Python의 동작은 진정한 모듈로 연산을 구현합니다. 관찰 한 동작은 C가 0으로 반올림하는 것과 일치합니다 (Fortran 동작이기도합니다).

0쪽으로 반올림 C 바람직하다 이유 중 하나는 결과 기대하는 것은 오히려 자연스러운 것입니다 -a / b같은 수를 -(a / b). 실제 모듈로 동작의 경우 -1 % 109로 평가되며 이는 -1 / 10-1이어야 함을 의미합니다 . 이것은 -(1 / 10)0 이기 때문에 다소 부 자연스럽게 보일 수 있습니다 .


는와 -1 modulo 10동일 하므로 두 답변 모두 정확합니다 9 modulo 10.

r = (a mod m)
a = n*q + r

당신은 확신 할 수 |r| < |n|있지만의 가치가 무엇인지는 알 수 없습니다 r. 부정적인 대답과 긍정적 인 두 가지 대답이 있습니다.


C89에서는 대답이 항상 정확하지만 모듈로 연산의 정확한 값 (나머지라고 함)은 정의되지 않았으므로 음의 결과 또는 양의 결과가 될 수 있습니다. C99에서는 결과가 정의됩니다.

그래도 긍정적 인 대답을 원하면 대답이 부정적이라면 간단히 10을 더할 수 있습니다.

모듈로 연산자가 모든 언어에서 동일하게 작동하도록하려면 다음 사항을 기억하십시오.

n mod M == (n + M) mod M

그리고 일반적으로 :

n mod M == (n + X * M) mod M

유클리드 나눗셈을 수행 a = b*q + r하는 것은 분수 a/b를 정수 몫으로 반올림 q한 다음 나머지를 계산하는 것과 같습니다 r.

표시되는 결과는 몫을 반올림하는 데 사용되는 규칙에 따라 다릅니다.

0쪽으로 반올림하면 (잘라 내기) C에서와 같이 0 주위의 대칭을 얻게됩니다.

truncate(7/3) = 2
7 = 3*2 + 1

truncate(-7/3) = -2
-7 = 3* -2 - 1

truncate(7/-3) = -2
7 = -3* -2 + 1

음의 무한대 (바닥)쪽으로 반올림하면 Python에서와 같이 나머지가 표시됩니다.

floor(7/3) = 2
7 = 3*2 + 1

floor(-7/3) = -3
-7 = 3* -3 + 2

floor(7/-3) = -3
7 = -3* -3 - 2

가장 가까운 int로 반올림하면 (원하는대로, 짝수 또는 0에서 멀어짐) 중앙 모듈로가됩니다.

round(7/3) = 2
7 = 3*2 + 1

round(8/3) = 3
8 = 3*3 - 1

round(-7/3) = -2
-7 = 3* -2 - 1

round(7/-3) = -2
7 = -3* -2 + 1

You could try to implement your own modulo with rounding toward positive infinity (ceil), and you would invent a rather unconventional modulo, but it would still be kind of modulo...


Since python 3.7 you can also use .remainder() from math built-in module.

Python 3.7.0a0 (heads/master:f34c685020, May  8 2017, 15:35:30)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
>>> math.remainder(-1, 10)
-1.0

From docs:

Return the IEEE 754-style remainder of x with respect to y. For finite x and finite nonzero y, this is the difference x - n*y, where n is the closest integer to the exact value of the quotient x / y. If x / y is exactly halfway between two consecutive integers, the nearest even integer is used for n. The remainder r = remainder(x, y) thus always satisfies abs(r) <= 0.5 * abs(y).

Special cases follow IEEE 754: in particular, remainder(x, math.inf) is x for any finite x, and remainder(x, 0) and remainder(math.inf, x) raise ValueError for any non-NaN x. If the result of the remainder operation is zero, that zero will have the same sign as x.

On platforms using IEEE 754 binary floating-point, the result of this operation is always exactly representable: no rounding error is introduced.

참고URL : https://stackoverflow.com/questions/1907565/c-and-python-different-behaviour-of-the-modulo-operation

반응형