programing

모듈로(%) 연산자는 파이썬에서 음수에서 어떻게 작동합니까?

cafebook 2023. 7. 17. 21:24
반응형

모듈로(%) 연산자는 파이썬에서 음수에서 어떻게 작동합니까?

정확히 어떻게.%연산자는 특히 음수가 포함된 경우 파이썬에서 작업합니까?

를 들어,왜 를들어왜, 예?-5 % 4하여 …로 합니다.3예를 들어, 라고 하기 보다는.-1?

연산자 (C나 C++와파이의, 연산는자달리모듈로썬▁(▁unlike▁(연산자▁python,c모리달듈로)%) 와 항상 분모(분할자)와 동일한 부호를 가진 숫자를 반환합니다.당신의 표현은 3을 산출합니다 왜냐하면

(-5) / 4 = -1.25 --> 바닥 (-1.25) = -2

(-5) % 4 = (-2 × 4 + 3) % 4 = 3.

음성이 아닌 결과가 종종 더 유용하기 때문에 C 동작보다 선택됩니다.예를 들어, 요일을 계산하는 것입니다.오늘이 화요일(2일)이라면 N일 전의 요일은 무엇입니까?Python을 사용하여 컴퓨팅할 수 있습니다.

return (2 - N) % 7

그러나 C에서 N ≥ 3이면 잘못된 숫자인 음수를 얻고 7을 추가하여 수동으로 수정해야 합니다.

int result = (2 - N) % 7;
return result < 0 ? result + 7 : result;

(언어별로 결과 부호가 결정되는 방법은 http://en.wikipedia.org/wiki/Modulo_operator 를 참조하십시오.)

Guido van Rossum의 설명은 다음과 같습니다.

http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html

기본적으로, 나머지 r을 갖는 a/b = q는 b*q + r = a와 0 < = r < b의 관계를 유지합니다.

파이썬에서 모듈로 연산자는 다음과 같이 작동합니다.

>>> mod = n - math.floor(n/base) * base

따라서 결과는 다음과 같습니다(당신의 경우:

mod = -5 - floor(-1.25) * 4
mod = -5 - (-2*4)
mod = 3

반면 C, JAVA, JavaScript와 같은 다른 언어들은 바닥 대신 잘라내기를 사용합니다.

>>> mod = n - int(n/base) * base

그 결과:

mod = -5 - int(-1.25) * 4
mod = -5 - (-1*4)
mod = -1

python에서 반올림에 대한 자세한 정보가 필요하면, 이것을 읽어보세요.

다른 답변, 특히 선택된 답변은 이 질문에 상당히 잘 답했습니다.하지만 저는 파이썬에서 일반적인 수학적 모듈로를 수행하기 위한 파이썬 코드와 함께 이해하기 더 쉬울 수 있는 그래픽 접근법을 제시하고자 합니다.

더미용 파이썬 모듈로

모듈로 함수는 무한한 숫자의 X축 위에서 나눗셈을 하는 동안 우리가 취하는 수학적 점프 후 얼마나 더 멀리 또는 뒤로 이동해야 하는지를 설명하는 방향 함수입니다.그래서 당신이 하고 있었다고 가정해 봅시다.7%3

enter image description here

그래서 당신의 대답은 +1이 될 것입니다. 하지만 반대 방향에서는-

enter image description here

당신의 대답은 -2일 것입니다.두 가지 모두 수학적으로 정확합니다.

마찬가지로 음수에 대해서도 2개의 계수가 있습니다. 예:-7%3할 수 있습니다. -1 또는 +2는 +2입니다.

enter image description here

순방향


enter image description here

역방향


수학에서, 우리는 안쪽으로 점프하는 것, 즉 양수의 경우 앞으로, 음수의 경우 뒤로 점프하는 것을 선택합니다.

그러나 Python에서는 모든 긍정적인 모듈로 작업에 대한 방향성이 있습니다.그러므로, 당신의 혼란은-

>>> -5 % 4 
3

>>> 5 % 4
1

다음은 파이썬의 내부 점프 유형 모듈로에 대한 파이썬 코드입니다.

def newMod(a,b):
    res = a%b
    return res if not res else res-b if a<0 else res

그러면 -

>>> newMod(-5,4)
-1

>>> newMod(5,4)
1

많은 사람들이 내향 점프 방식에 반대하겠지만, 저의 개인적인 의견은 이것이 더 낫다는 것입니다!!

지적된 바와 같이, 파이썬 모듈로는 다른 언어의 관습에 대해 합리적인 예외를 만듭니다.

이는 특히 음의 숫자와 조합하여 사용할 때 매끄러운 동작을 제공합니다.// "-벡터", "-벡터"%modulo는 종종 (math.divmod에서처럼):

for n in range(-8,8):
    print n, n//4, n%4

생성물:

 -8 -2 0
 -7 -2 1
 -6 -2 2
 -5 -2 3

 -4 -1 0
 -3 -1 1
 -2 -1 2
 -1 -1 3

  0  0 0
  1  0 1
  2  0 2
  3  0 3

  4  1 0
  5  1 1
  6  1 2
  7  1 3
  • 파이% 0 양의 값을 합니다* 0을 출력합니다.
  • 파이//합니다.

적절한 피연산자가 양성이면 됩니다반면에11 % -10 == -9

음수가 있는 정수 나눗셈 및 모드를 처리하는 가장 좋은 방법은 없습니다.그렇다면 좋을 것 같습니다.a/b의 크기와 반대의 부호였습니다.(-a)/b그렇다면 좋을 것 같습니다.a % b정말 모듈롭이었습니다.우리가 정말로 원하기 때문에.a == (a/b)*b + a%b처음 두 개는 호환되지 않습니다.

어느 것을 지켜야 할지는 어려운 질문이고, 양쪽 모두에 대한 주장이 있습니다.와 C의 둥근 ( 0 한 C 와 C + + + 근 따 정 수 나 눗 셈 라 서 의 을 향 둥 따 ▁c ▁towards 서 라 ▁division 나▁( 눗 셈 ▁0 ▁( ▁integer ▁c soa/b == -((-a)/b)않은 것으로 보입니다.), 파이않습니다그지렇은썬▁),다.

사용할 수 있는 항목:

result = numpy.fmod(x,y)

기호를 유지합니다. numpy fmod 설명서를 참조하십시오.

파이썬의 나눗셈도 C: 고려와 다르다는 점도 언급할 가치가 있습니다.

>>> x = -10
>>> y = 37

C에서 당신은 결과를 기대합니다.

0

파이썬에서 x/y는 무엇입니까?

>>> print x/y
-1

%는 모듈로이고 나머지는 아닙니다!C 수율의 x%y인 동안

-10

비단뱀의 수확량

>>> print x%y
27

C에서와 같이 둘 다 얻을 수 있습니다.

부서:

>>> from math import trunc
>>> d = trunc(float(x)/y)
>>> print d
0

나머지(위에서 나눗셈 사용):

>>> r = x - d*y
>>> print r
-10

이 계산은 가장 빠르지는 않지만 x와 y의 기호 조합에 대해 작동하여 C와 동일한 결과를 얻을 수 있으며 조건부 문을 피할 수 있습니다.

이것이 모듈로가 사용되는 이유입니다.일련의 숫자를 통해 모듈로를 수행하면 다음과 같이 값의 사이클이 제공됩니다.

ans = num % 3
번호 앤스
3 0
2 2
1 1
0 0
-1 2
-2 1
-3 0

저도 파이썬의 이상한 행동이라고 생각했습니다.(서류상으로는) 분열을 잘 해결하지 못했던 것으로 드러났습니다.저는 지수에 0, 나머지에 -5의 값을 주고 있었습니다.끔찍해요정수 숫자의 기하학적 표현을 잊어버렸습니다.숫자선으로 주어진 정수의 기하학적 구조를 떠올리면 몫과 나머지에 대한 정확한 값을 얻을 수 있고, 파이썬의 동작이 괜찮은지 확인할 수 있습니다. (비록 당신은 이미 오래전에 고민을 해결했다고 생각합니다.)

@Deekshant는 시각화를 사용하여 이를 잘 설명했습니다.%(modulo)를 이해하는 또 다른 방법은 간단한 질문입니다.

X축에서 나눗셈으로 나눌 수 있는 배당에 가장 가까운 작은 숫자는?

몇 가지 예를 살펴보겠습니다.

5 % 3 

5는 배당금, 3은 배당금입니다.위에서 질문하신 3번은 가장 작은 숫자로 나눗셈을 할 수 있습니다.ans는 5 - 3 = 2입니다.양의 배당금의 경우 가장 작은 숫자는 항상 배당금의 오른쪽에 있습니다.

-5 % 3

3으로 나눌 수 있는 가장 작은 수는 -6이므로 -5 - (-6) = 1이 됩니다.

-5 %4

4로 나눌 수 있는 가장 작은 수는 -8이므로 -5 - (-8) = 3이 됩니다.

Python은 이 방법으로 모든 모듈로 표현식에 답합니다.다음에는 표현식이 어떻게 실행되는지 이해할 수 있기를 바랍니다.

저는 모든 입력 사례를 포괄하는 일반적인 답변을 쓰려고 했습니다. 왜냐하면 많은 사람들이 다양한 특수 사례(OP의 경우뿐만 아니라 특히 오른쪽의 음수 값에 대해서도)에 대해 질문하기 때문입니다. 그리고 그것은 정말로 모두 같은 질문입니다.

가 입니까?a % b실제로 우리에게 파이썬으로 제공합니까, 말로 설명합니까?

라고 가정하면,a그리고.b둘 중 하나입니다.float 및/는int값, 유(아)이 아님)math.inf,math.nan 그 ① ②b0이 아닙니다.

»c부호가 있는 고유 번호로, 그래서a - c는 로나 수있는으로 수 있습니다.b그리고.abs(c) < abs(b)그것은 될 것입니다.int 때에a그리고.b 다입니다 int a 리고a.float(정수와 정확히 같더라도) 다음 중 하나일 때 a또는b인트입니다.

예:

>>> -9 % -5
-4
>>> 9 % 5
4
>>> -9 % 5
1
>>> 9 % -5
-1

부호 보존은 부동 소수점 번호에도 작동합니다.a는 로나 수있는으로 수 있습니다.b구별되는 것이 가능합니다.0.0그리고.-0.0으로 간주), 결(0" 부소에부서을됨의호미이화다), 부일니합치호과recalling와 일치합니다.b.

개념 증명:

import math

def sign(x):
    return math.copysign(1, x)

def test(a: [int, float], b: [int, float]):
    c = a % b
    if isinstance(a, int) and isinstance(b, int):
        assert isinstance(c, int)
        assert c * b >= 0 # same sign or c == 0
    else:
        assert isinstance(c, float)
        assert sign(c) == sign(b)
    assert abs(c) < abs(b)
    assert math.isclose((a - c) / b, round((a - c) / b))

가능한 모든 부호와 유형 조합을 포함하고 부동소수점 부정확성을 설명하는 방식으로 이를 표현하는 것은 조금 어렵지만, 저는 위에 있는 것에 대해 꽤 자신 있습니다.하나의 구체적인 gotcha는float그에 s, 는, 그, 다에 대한 a % b 때때로 주는 것처럼 보일 도 있습니다.b0사실, 그것은 단순히 매우 가까운 가치를 제공합니다.b분할 결과가 정확하지 않았기 때문입니다.

>>> # On my version of Python
>>> 3.5 % 0.1
0.09999999999999981
>>> # On some other versions, it might appear as 0.1,
>>> # because of the internal rules for formatting floats for display

면 어쩌지abs(a) < abs(b)?

많은 사람들이 이것이 특별한 경우라고 생각하거나, 어떤 이유로 무슨 일이 일어나는지 이해하는 데 어려움을 겪는 것 같습니다.하지만 여기에는 특별한 것이 없습니다.

를 들어, 고: 려를 해 보세요.-1 % 3양의 양으로 얼마만큼(왜냐하면3요?-1를 로나수 얻결위 기하여과를로 나누기 .3?-1는 의해분지않음으로 나눌 수 .3;-1 - 1이라-2 수 , 또한분수없지만할할,만또▁which없지수▁but▁is▁not한분할할.-1 - 2이라-3는 로나 수눌있으로 나눌 수 .3는 (으)로 )-1몇번로). 뺄으셈을 ,2는 다시; 그러므로 우는분돌니다아갑로그로열므; 러리로므▁we그.2예측된 답입니다. 그리고 확인할 수 있습니다.

>>> -1 % 3
2

럼그는?b0과 같습니까?

그것은 그럴거다.raise ZeroDivisionError여부관이없의 여부에 b정수 0, 부동 소수점 양의 0 또는 부동 소수점 음의 0입니다.특히, NaN 값은 발생하지 않습니다.

특수 부동 소수점 값은 어떻습니까?

예대로상,nan 및부 무대 한는에 부호가 값.a을 생산합니다.nan결과, 계는한되 속▁as 한▁long.b0이 아닙니다(다른 모든 항목보다 우선함). nan합니다.b▁in로가 나다nan뿐만 아니라.NaN은 서명할 수 없으므로 다음과 같은 기호가 표시됩니다.b이러한 경우에는 관련이 없습니다.

또한예로대상,로▁also또대상.inf % inf, 주다, 주다, 주다, 주다, 주다, 주다, 주다, 주다, 주다.nan이라면, 우리는 무한한 양을 공유할 입니다.a의 한히무은에bs, "어느 무한대가 더 큰지" 또는 얼마나 많은지 말할 수 없습니다.

유일하게 약간 혼란스러운 경우는b부호 있는 무한대 값입니다.

>>> 0 % inf
0.0
>>> 0 % -inf
-0.0
>>> 1 % inf
1.0
>>> 1 % -inf
-inf

언제나 그렇듯, 결과는 다음과 같습니다.b.0무한대를 포함한 모든 것(NaN 제외)으로 나눌 수 있습니다.하지만 다른 어떤 것도 무한대로 균등하게 나누지는 않습니다.한다면a는 와부가같습다니호▁▁sign▁same와 같은 부호를 가지고 .b는 단순히 결는간히단입니다.a다를 (으), (으)로 됩니다.b 왜죠음?요, 생보세해각.-1 % inf우리가 뺄 수 있는 유한한 값은 없습니다.-1에도기위해에 도착하기 0(무한대로 나눌 수 있는 고유한 값).그래서 우리는 무한대로 계속 가야 합니다.에도 같은 논리가 적용됩니다.1 % -inf모든 징후가 뒤바뀐 채로

다른 종류는 어떻습니까?

종류에 따라 다릅니다.예를 들어, Decimal type은 연산자를 오버로드하여 기능적으로 다음과 같은 종류의 값을 나타내더라도 결과가 분자의 부호를 취하도록 합니다.float네, 물론 현악기는 전혀 다른 용도로 사용합니다.

왜 항상 긍정적인 결과를 주지 않거나, 사인을 받아라.a?

동작은 정수 나눗셈에 의해 동기 부여됩니다.하는 동안에%숫자와 입력을 되었으며, 부동소수숫함작께며정, 처록도으었특며과, 같다다습니과음에 결과입니다.floats는 그것과 일치하기 위해 줄을 섭니다.

다음 항목을 선택한 후a // b결과를 , 바닥분 결제할기위해하공를과,위,%행동은 유용한 불변량을 보존합니다.

>>> def check_consistency(a, b):
...     assert (a // b) * b + (a % b) == a
... 
>>> for a in range(-10, 11):
...     for b in range(-10, 11):
...         if b != 0:
...             check_consistency(a, b) # no assertion is raised
...

즉, 계수 값을 다시 추가하면 정수 나눗셈을 수행하여 생성된 오류가 수정됩니다.

(물론, 이것은 첫 번째 섹션으로 돌아가서 다음과 같이 말할 수 있습니다.a % b 순단계를 계산합니다.a - ((a // b) * b)하지만 그것은 단지 깡통을 앞으로 내동댕이칠 뿐입니다. 우리는 여전히 설명해야 합니다.//부호 있는 값, 특히 플로트에 대해 수행합니다.)

픽셀 좌표를 타일 좌표로 변환할 때 한 가지 실용적인 응용 프로그램입니다. //픽셀 좌표를 포함하는 타일을 알려줍니다.%타일 내의 오프셋을 알려줍니다.16x16 가정하면, x 타일은 16x16 타일입니다.0가 x인 을 포함합니다.0..15 일포함타1 값 픽 좌 표 값 해 합 니 다 에 해당합니다.16..31등등. 픽셀좌, 예들어라고 100우리는 그것이 타일 안에 있다는 것을 쉽게 계산할 수 있습니다.100 // 16 == 6 오프셋 및프셋오100 % 16 == 4해당 타일의 왼쪽 가장자리에 있는 픽셀입니다.

우리는 원산지 반대편의 타일을 처리하기 위해 아무것도 바꾸지 않아도 됩니다. 표의타에 있는 -1의 왼쪽에 있는 다음 16픽셀 좌표를 설명해야 합니다.0 즉,-16..-1 실제로,을 발견합니다 를 들어.그리고 실제로 우리는 그것을 발견합니다. 예를 예로 들 수 있습니다. -13 // 16 == -1 좌표는 타일 ), 그리고 (으)로 표시합니다.-13 % 16 == 3(타일의 왼쪽 가장자리로부터 거리).

타일 너비를 양수로 설정하여 타일 내 좌표가 왼쪽에서 오른쪽으로 진행되도록 정의했습니다.따라서 점이 특정 타일 내에 있다는 것을 알고 있으면 항상 해당 오프셋 계산에 대한 긍정적인 결과가 필요합니다.파이의%연산자는 Y축의 양쪽에서 그것을 제공합니다.

다른 방식으로 작동하려면 어떻게 해야 합니까?

math.fmod분자의 부호를 취할 것입니다.두 개의 입력에 를 반환하고 에 대한 시킵니다.anan 이 있는 b값:

>>> math.fmod(-13, 16)
-13.0
>>> math.fmod(13, -16)
13.0
>>> math.fmod(1, -inf) # not -inf
1.0
>>> math.fmod(inf, 1.0) # not nan
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: math domain error

방식으로 됩니다. - 은 다음과 같습니다. - 0은 다음과 같습니다.b합니다. 경우 임의의 예를제합다니입니다. 그렇지 않은 경우nan은 재현원인a입니다.nan결과.

이것도 당신의 요구에 맞지 않는다면, 가능한 모든 코너 케이스에 대해 정확하게 원하는 동작을 신중하게 정의하고, 내장된 옵션과 다른 부분을 파악하고, 래퍼 기능을 만드세요.

언급URL : https://stackoverflow.com/questions/3883004/how-does-the-modulo-operator-work-on-negative-numbers-in-python

반응형