자바에서 할 때
a % b
a가 음수이면 b로 감싸는 대신 부정적인 결과를 반환합니다. 이 문제를 해결하는 가장 좋은 방법은 무엇입니까? 내가 생각할 수있는 유일한 방법은
a < 0 ? b + a : a % b
답변
a % b = a-a / b * b; 즉, 나머지입니다.
할 수 있습니다 (a % b + b) % b
이 표현식은 결과 가 양수인지 음수 인지 에 관계없이 (a % b)
반드시이보다 낮기 때문에 작동합니다 . 이 추가 의 음의 값을 담당 하기 때문에, 사이의 네거티브 값이 과 , 반드시 하부보다 긍정적. 마지막 모듈은 경우가 이후 경우,로 시작하는 긍정적 긍정적 보다 크게 될 것이다 . 따라서 다시 더 작게 만듭니다 ( 음수 값 에는 영향을주지 않음 ).b
a
b
a
(a % b)
-b
0
(a % b + b)
b
a
a
(a % b + b)
b
(a % b + b) % b
b
a
답변
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
당신은 단지 사이의 균일 한 분산이 필요한 경우 0
와 n-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을 정확하게 예측할 수 있다면 아마도 이길 것입니다.
(편집 : 수식을 수정했습니다.)