프로그래밍 언어 설계자가 모듈로 연산의 결과에 어떤 부호가 있는지 결정할 때 어떤 근거가 사용됩니까?


9

를 통과 모듈로 연산 (사이의 차이 탐험하는 동안 입력 한 길 remmod 내가 건너 온)

수학에서 모듈로 연산의 결과는 유클리드 디비전의 나머지입니다. 그러나 다른 규칙도 가능합니다. 컴퓨터와 계산기에는 숫자를 저장하고 나타내는 다양한 방법이 있습니다. 따라서 모듈로 연산의 정의는 프로그래밍 언어 및 / 또는 기본 하드웨어에 따라 다릅니다.

질문 :

  • 를 통과 유클리드 부문 나는이 작업의 remainnder 항상 긍정적 인 발견 (0). 기본 컴퓨터 하드웨어의 어떤 제한으로 인해 프로그래밍 언어 디자이너가 수학과 다른가?
  • 모든 프로그래밍 언어에는 모듈로 연산의 결과가 부호를 갖는 규칙에 따라 사전 정의되거나 정의되지 않은 규칙이 있습니다. 이 규칙을 만드는 동안 어떤 근거가 채택됩니까? 그리고 기본 하드웨어가 문제라면 프로그래밍 언어와 관계없이 규칙에 따라 규칙을 변경해서는 안됩니까?

1
내 코드에서는 거의 항상 나머지가 아닌 모듈로가 필요합니다. 왜 나머지가 그렇게 인기가 있는지 모르겠다.
코드 InChaos


1
당신이 인용 한 부분을 넘어서서 Wikipedia 기사를 계속 읽는다면, 그것은 당신이 인용 한 것을 잘 설명합니다. 그 설명은 어떻습니까?
Robert Harvey

1
하나의 관련 질문은 이러한 작업 중 어떤 것이 CPU 명령어에 직접 매핑되는지입니다. c에는 구현이 정의되어 있으며 가능한 많은 플랫폼에서 하드웨어에 직접 매핑한다는 c 철학에 맞습니다. 따라서 CPU마다 다를 수있는 것을 지정하지 않습니다.
코드 InChaos

5
@BleedingFingers Programming은 종종 0으로가는 정수 나누기를 사용합니다 (예 :) (-3)/2 == -1. 이 정의는 유용 할 수 있습니다. 당신이 원하는 때 %수행이 분열과 일치하도록 x == (x/y)*y + x % y당신의 정의와 끝까지 %C #으로 사용된다.
코드 InChaos

답변:


7

모든 최신 컴퓨터의 하드웨어는 성능에 아무런 영향을 미치지 않고 부호의 모드 작업을 구현하기에 충분히 강력합니다. 이것은 이유가 아닙니다.

대부분의 컴퓨터 언어에 대한 일반적인 기대는 (a div b) * b + (a mod b) = a입니다. 다시 말해, div와 mod가 함께 고려되면 숫자를 다시 확실하게 다시 합칠 수있는 부분으로 나눕니다. 이 요구 사항은 C ++ 표준에 명시되어 있습니다. 이 개념은 다차원 배열의 인덱싱과 밀접한 관련이 있습니다. 나는 그것을 자주 사용했다.

이것으로부터 div와 mod는 b가 양수인 경우 (보통 그대로) a의 부호를 유지한다는 것을 알 수 있습니다.

일부 언어는 mod와 관련된 'rem ()'함수를 제공하며 다른 수학적 근거가 있습니다. 나는 이것을 사용할 필요가 없었습니다. 예를 들어 Gnu C의 frem ()을 참조하십시오.


나는 그것이 긍정적이거나 그렇지 않다면 rem(a,b)더 likley 라고 생각합니다 . mod(a,b)mod(a,b) + b
user40989

3
(a div b) * b + (a mod b) = a-너무 너무. 사실 Wikipedia 가 유클리드 부서에서 음수로 확장 하는 방법과 달리 (특히 "나머지는 절대 음수가 될 수없는 네 가지 숫자 중 하나입니다.") 나는 항상 나머지 가 음수 일 있다는 것을 배웠기 때문에 나를 혼동합니다. 그 수준의 모든 수학 수업에서.
이즈 카타

@ user40989 : 나는 그것을 사용하지 않을 것이라고 말했다. 편집 참조!
david.pfx

4

일반적으로 원하는 프로그래밍 X == (X/n)*n + X%n; 따라서 모듈로 정의 방법은 정수 나누기 정의 방법에 따라 다릅니다.

이를 염두에두고, " 언어 구분이 작동하는 방식을 프로그래밍 언어 디자이너가 결정할 때 어떤 이론적 근거가 사용됩니까? "

실제로 약 7 가지 선택이 있습니다.

  • 음의 무한대로 반올림
  • 양의 무한대로 반올림
  • 0으로 반올림
  • "가장 반올림"의 여러 버전 (0.5와 같은 반올림 방법에 차이가 있음)

이제 고려하십시오 -( (-X) / n) == X/n. 불일치 (부동 소수점의 경우 사실)와 비논리적 인 (버그의 원인이 될 수 있으며 잠재적으로 누락 된 최적화) 다른 것이 있기 때문에 이것이 사실이기를 원합니다. 이것은 정수 나누기 (무한대를 향한 반올림)에 대한 처음 두 가지 선택을 바람직하지 않게 만듭니다.

모든 "가장 가까운"선택은 특히 비트 맵 (예 :)과 같은 작업을 수행 할 때 프로그래밍에 어려움을 겪습니다 offset = index / 8; bitNumber = index%8;.

이것은 "잠재적으로 가장 제정신"선택으로 0으로 반올림합니다. 이는 모듈로가 분자와 같은 부호 (또는 0)로 값을 반환한다는 것을 의미합니다.

참고 : 또한 대부분의 CPU (내가 알고있는 모든 CPU)는 동일한 "0에서 0으로"정수 나누기를 수행합니다. 이것은 같은 이유로 발생할 수 있습니다.


그것은 나누기 : 그러나 분열을 절단하는 것은 물론 자신의 일관성을 가지고 (a+b*c)/b == a % b하고 a >> n == a / 2 ** n있는 부문은 제정신 행동을 가지고 낭패.
dan04

첫 번째 예는 이해가되지 않습니다. 두 번째 예는 프로그래머에게 엉망입니다. 긍정적 인 a와 긍정적 인 n의 경우 일관성이며, 부정적 a와 긍정적 인 n의 경우 시프트 권리가 정의되는 방식 (산술 대 논리)과 부정적 n의 경우 (예 :)에 따라 다릅니다 1 >> -2 == a / 2 ** (-2).
Brendan

첫 번째 예는 오타입니다. (a + b * c) % b == a % b즉, %오퍼레이터는 배당에서 제수 주기적이며 이는 종종 중요합니다. 예를 들어, 바닥 구분을 day_count % 7사용하면 요일을 제공하지만 잘림 구분을 사용하면 시대 이전 날짜로 구분됩니다.
dan04

0

먼저, 모듈로 b가 a-b * (a div b)와 같아야한다는 것을 반복하고 언어가이를 제공하지 않으면 수학적 혼란에 빠지게됩니다. 이 표현 a-b * (a div b)는 실제로 모듈로 b를 계산하는 구현 횟수입니다.

몇 가지 가능한 근거가 있습니다. 첫 번째는 최대 속도를 원한다는 것입니다. 따라서 div b는 사용 된 프로세서가 제공하는 것으로 정의됩니다. 프로세서에 "div"명령어가있는 경우 div b는 div 명령어가 수행하는 모든 것입니다 (전적으로 미치 않은 것이 아닌 한).

두 번째는 특정한 수학적 행동을 원한다는 것입니다. 먼저 b> 0으로 가정하겠습니다. div b의 결과를 0으로 반올림하는 것이 매우 합리적입니다. 따라서 4 div 5 = 0, 9 div 5 = 1, -4 div 5 = -0 = 0, -9 div 5 = -1입니다. 이것은 (-a) div b =-(a div b) 및 (-a) modulo b =-(a modulo b)를 제공합니다.

이것은 상당히 합리적이지만 완벽하지는 않습니다. 예를 들어 (a + b) div b = (a div b) + 1은 유지되지 않습니다. 예를 들어 a = -1이면 말입니다. 고정 된 b> 0 인 경우, 일반적으로 (b) 가능한 값은 div b가 0 인 2b-1 값 a -b + 1에서 b-1을 제외하고는 div b가 동일한 결과를 제공 할 수 있습니다. 또한 a가 음수이면 모듈로 b가 음수임을 의미합니다. 모듈로 b는 항상 0에서 b-1 사이의 숫자가 되길 원합니다.

반면에 a의 연속적인 값을 통과 할 때 모듈로 b는 0에서 b-1까지의 값을 통과 한 다음 0으로 다시 시작하도록 요청하는 것이 매우 합리적입니다. 그리고 (a + b) div b는 (a div b) + 1이어야합니다.이를 위해서는 div b의 결과를-무한으로 반올림하여 -1 div b = -1이되도록합니다. 다시 한 번 단점이 있습니다. (-a) div b =-(a div b)는 유지되지 않습니다. 반복해서 2 또는 임의의 숫자 b> 1로 나누면 결과는 0이되지 않습니다.

갈등이 있기 때문에 언어는 어떤 장점이 그들에게 더 중요한지를 결정하고 그에 따라 결정해야합니다.

음수 b의 경우 대부분의 사람들은 div b와 modulo b가 처음에 있어야 할 것에 대해 머리를 맞출 수 없으므로 간단한 방법은 div b = (-a) div (-b) 및 b <0 인 경우 a 또는 b = (-a) 모듈로 (-b)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.