[java] Java의 모듈러스가 음수로 작동하도록하는 가장 좋은 방법은 무엇입니까?

자바에서 할 때

a % b

a가 음수이면 b로 감싸는 대신 부정적인 결과를 반환합니다. 이 문제를 해결하는 가장 좋은 방법은 무엇입니까? 내가 생각할 수있는 유일한 방법은

a < 0 ? b + a : a % b



답변

a % b = a-a / b * b; 즉, 나머지입니다.

할 수 있습니다 (a % b + b) % b


이 표현식은 결과 가 양수인지 음수 인지 에 관계없이 (a % b)반드시이보다 낮기 때문에 작동합니다 . 이 추가 의 음의 값을 담당 하기 때문에, 사이의 네거티브 값이 과 , 반드시 하부보다 긍정적. 마지막 모듈은 경우가 이후 경우,로 시작하는 긍정적 긍정적 보다 크게 될 것이다 . 따라서 다시 더 작게 만듭니다 ( 음수 값 에는 영향을주지 않음 ).baba(a % b)-b0(a % b + b)baa(a % b + b)b(a % b + b) % bba


답변

Java 8부터 Math.floorMod (int x, int y)Math.floorMod (long x, long y)를 사용할 수 있습니다. 이 두 방법 모두 Peter의 대답과 동일한 결과를 반환합니다.

Math.floorMod( 2,  3) =  2
Math.floorMod(-2,  3) =  1
Math.floorMod( 2, -3) = -1
Math.floorMod(-2, -3) = -2


답변

아직 Java 8을 사용하지 않거나 사용할 수없는 사람들을 위해 Guava는 Guava 11.0부터 사용할 수 있는 IntMath.mod () 를 사용 하여 구출했습니다 .

IntMath.mod( 2, 3) = 2
IntMath.mod(-2, 3) = 1

한 가지주의 사항 : Java 8의 Math.floorMod ()와 달리 제수 (두 번째 매개 변수)는 음수가 될 수 없습니다.


답변

수 이론에서 결과는 항상 양수입니다. 모든 프로그래머가 수학자는 아니기 때문에 컴퓨터 언어에서는 이것이 항상 그런 것은 아니라고 생각합니다. 내 두 센트, 나는 그것을 언어의 디자인 결함이라고 생각하지만 지금은 바꿀 수 없습니다.

= MOD (-4,180) = 176 = MOD (176, 180) = 176

180 * (-1) + 176 = -4 180 * 0 + 176 = 176과 같기 때문에

http://mathworld.wolfram.com/Congruence.html 의 시계 예제를 사용하면
duration_of_time mod cycle_length가 -45 분이라고 말하지 않고 두 답변 모두 기본 방정식을 충족하더라도 15 분이라고 말할 것입니다.


답변

Java 8에는 Math.floorMod이 있지만 매우 느립니다 (구현에는 다중 분할, 곱셈 및 조건부가 있음). 그러나 JVM에 고유 한 최적화 된 스텁이있어 속도를 크게 높일 수 있습니다.

없이 이것을 수행하는 가장 빠른 방법 floorMod은 여기의 다른 답변과 같지만 조건부 분기가없고 느린 작업이 하나뿐입니다 %.

n이 양수이고 x가 무엇이든 될 수 있다고 가정합니다.

int remainder = (x % n); // may be negative if x is negative
//if remainder is negative, adds n, otherwise adds 0
return ((remainder >> 31) & n) + remainder;

결과 n = 3:

x | result
----------
-4| 2
-3| 0
-2| 1
-1| 2
 0| 0
 1| 1
 2| 2
 3| 0
 4| 1

당신은 단지 사이의 균일 한 분산이 필요한 경우 0n-1아닌 정확한 모드 연산자를하고 x의 근처 클러스터하지 않는 0이 더 명령어 수준의 병렬 처리하고 느린로, 다음, 더 빨리 될 것입니다 %계산이 병렬로 발생합니다 결과에 의존하지 않기 때문에 부품.

return ((x >> 31) & (n - 1)) + (x % n)

위의 결과는 다음과 n = 3같습니다.

x | result
----------
-5| 0
-4| 1
-3| 2
-2| 0
-1| 1
 0| 0
 1| 1
 2| 2
 3| 0
 4| 1
 5| 2

입력이 int의 전체 범위에서 임의적이면 두 솔루션의 분포는 동일합니다. 입력 클러스터가 0에 가까우 n - 1면 후자의 솔루션에서 결과가 너무 적습니다 .


답변

다음은 대안입니다.

a < 0 ? b-1 - (-a-1) % b : a % b

이것은 다른 공식 [(a % b + b) % b]보다 빠르거나 빠르지 않을 수 있습니다. 다른 공식과 달리 분기를 포함하지만 모듈로 연산을 하나 덜 사용합니다. 컴퓨터가 <0을 정확하게 예측할 수 있다면 아마도 이길 것입니다.

(편집 : 수식을 수정했습니다.)


답변