Java는 음수로 모듈러스 계산을 어떻게 수행합니까?


93

모듈러스를 잘못하고 있습니까? Java -13 % 64에서는 평가해야 -13하지만 51.


102
@Dan 정적 메인 보이드 없이도 ... 코드를 봅니다.
Joris Meys

22
내가 얻을 -13 및 64 == -13
Grodriguez

7
어떻게 당신은 -13보다 51 ratehr을 받고있다.
Raedwald

3
모듈러스를 전혀 수행하지 않습니다. Java에는 모듈로 연산자가 없습니다. %나머지 연산자입니다.
Marquis of Lorne

3
혼란스러운 질문 : 다른 사람들이 말하는 것처럼 Java 8은 -13을 제공합니다. 어떤 Java 버전을 사용 했습니까?
Jan Żankowski

답변:


104

음수의 계수에 대한 두 정의가 모두 사용됩니다. 일부 언어는 하나의 정의를 사용하고 일부는 다른 정의를 사용합니다.

음수 입력에 대해 음수를 얻으려면 다음을 사용할 수 있습니다.

int r = x % n;
if (r > 0 && x < 0)
{
    r -= n;
}

마찬가지로 음수 입력에서 음수를 반환하는 언어를 사용하고 있고 양수를 선호하는 경우 :

int r = x % n;
if (r < 0)
{
    r += n;
}

3
n이 음수이면 제대로 작동하지 않습니다. Java 7 언어 사양 (섹션 15.17.3)의 동일한 예제를 사용하는 경우 : (-5) % (-3) = -2. -3을 추가하면 작동하지 않습니다. 값이 양수인지 확인하려면 n의 절대 값을 추가해야합니다.
partlov

6
Java에서 음수 모듈로는 아무것도 변경하지 않습니다. 어쨌든 Abs ()를 사용하면 r = x % abs (n)을 작성하십시오. 나는 if 문이 마음에 들지 않고, r = ((x % n) + n) % n을 쓰고 싶습니다. 2 모듈로 (2,4,8,16 등)의 거듭 제곱과 긍정적 인 대답에 대해서는 이진 마스크 ​​r = x & 63을 고려하십시오.
Fabyen

3
Java의 맥락에서 (질문 태그에 따라)이 대답은 본질적으로 "잘못된"것입니다. 표현식이 주어지면 x % yA) x가 음수이면 나머지는 음수 x % y == -(-x % y)입니다. B)의 부호는 y효과가 없습니다. 즉x % y == x % -y
Bohemian

72

"수학적으로"둘 다 정확하기 때문에 :

-13 % 64 = -13 (on modulus 64)  
-13 % 64 = 51 (on modulus 64)

옵션 중 하나는 Java 언어 개발자가 선택해야했으며 다음을 선택했습니다.

결과의 부호는 배당금의 부호와 같습니다.

Java 사양에서 다음과 같이 말합니다.

https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.17.3


8
질문은 " -13 % 64 = 51내가 기대했을 때 Java가 나에게주는 이유는 -13무엇입니까?"입니다.
Pascal Cuoq 2010

5
@pascal : java는 수학에 대한 올바른 정의를 제공하며 예상 한대로 구현 된 방식을 제공합니다.

9
수학적으로 정상 동작은 Java 8에서 사용할 수 있습니다. Math.floorMod
Jesse Glick

1
15.17.3의 무언가 . 나머지 연산자 % 예제는 명확하지 않습니다. int result = (-5) % 3;-2를 준다. int result = (-3) % 5;-3을 제공합니다. 일반적으로 int result = (-a) % b;| -a | > b. 적절한 결과를 얻으려면 | -a | <b 우리는 제수를 감싸 야합니다. int result = ((-a) % b) + b;부정적 또는 int result = (((-a) % b) + b) % b;긍정적 또는 부정적위한
오즈 에드

@Caner 나는 이것을 이해하지 못했습니다. 어떻게 둘 다 같을 수 있습니까?
Kishore Kumar Korada

20

Java로 작업하고 있습니까? Java는 예상대로 -13 % 64 = -13을 제공하기 때문입니다. 배당금의 징조!


15

Java에 대한 결과가 잘못되었습니다. 어떻게 도달했는지 (귀하의 프로그램, 구현 및 Java 버전) 컨텍스트를 제공하십시오.

로부터 Java 언어 사양

15.17.3 나머지 연산자 %
[...]
이진 숫자 승격 (§5.6.2) 후 정수인 피연산자에 대한 나머지 연산은 (a / b) * b + (a % b)가 다음과 같은 결과 값을 생성합니다. ㅏ.
15.17.2 나누기 연산자 /
[...]
정수 나누기는 0으로 반올림합니다.

/는 0으로 반올림되므로 (결과는 0)이 경우 %의 결과는 음수 여야합니다.


15.17.3의 무언가 . 나머지 연산자 % 예제는 명확하지 않습니다. int result = (-5) % 3;-2 int result = (-3) % 5;제공 -3 제공 일반적으로 int result = (-a) % b;| -a | > b 적절한 결과를 얻으려면 | -a | <b 우리는 제수를 감싸 야합니다. int result = ((-a) % b) + b;음수 a 또는 int result = (((-a) % b) + b) % b;양수 또는 음수 a.
Oz Edri 2015

1
귀하의 의견이 명확하지 않습니다. 그 부분 올바른 결과를 정의하고 예제는 해당 정의에 동의합니다. 예를 들어 (-3) % 5정의에 따른 올바른 결과는 -3이며 올바른 Java 구현은 해당 결과를 생성해야합니다.
starblue

제 자신을 올바르게 설명하지 않은 것 같습니다. | -a | <b에서 "정답"이 의미하는 것은 긍정적 인 결과를 얻으려면 b를 추가하여 a % b에서 주어진 결과를 "포장"해야한다는 것입니다. 내 예에서, (-3)%5참으로 제공 -3, 우리는 긍정적 인 나머지를 원한다면 우리는 5를 추가해야하고 결과가 될 것2
오즈 에드

6

당신이 사용할 수있는

(x % n) - (x < 0 ? n : 0);

3
@ruslik 다음 작업도 수행 할 수 있습니다 ((x % k) + k) % k.. (비록 당신은 아마 더 읽을 수 있습니다.)
존 Kurlak

2
@JohnKurlak 당신 버전은 다음과 같이 작동합니다 : 4 % 3 = 1 OR 4 % -3 = -2 OR -4 % 3 = 2 OR -4 % -3 = -1하지만 ruslik의 버전은 다음과 같이 작동합니다 : 4 % 3 = 1 또는 4 % -3 = 1 % 3 = -4 -4 -4 % -3 OR = 2
Joschua

1
@Joschua 이것을 지적 해 주셔서 감사합니다. 내 코드는 모듈러스 결과가 [0, sign(divisor) * divisor)대신 범위에 있기를 원할 때 유용합니다 [0, sign(dividend) * divisor).
John Kurlak

3

당신의 대답은 위키피디아에 있습니다 : 모듈로 연산

Java에서 모듈로 연산의 사인온은 배당금의 사인온과 동일합니다. 나머지 나누기 연산에 대해 이야기하고 있기 때문에 -13/64 = 0이므로 -13을 반환합니다. -13-0 = -13.

편집 : 죄송합니다, 귀하의 질문을 오해했습니다 ... 당신이 맞습니다, 자바는 -13을 제공해야합니다. 더 많은 주변 코드를 제공 할 수 있습니까?


2

음수 피연산자가있는 모듈로 산술은 언어 설계자에 의해 정의되며, 언어 설계자는이를 언어 구현에 맡기고 정의를 CPU 아키텍처에 연기 할 수 있습니다.

Java 언어 정의를 찾을 수 없습니다. 나머지 연산자 %에
대한 Java 언어 사양 인 Ishtar 는 결과의 부호가 분자의 부호와 동일하다고 말합니다.


1

이를 극복하기 위해 64양수가 될 때까지 음수 값에 더할 수 있습니다.

int k = -13;
int modbase = 64;

while (k < 0) {
    k += modbase;
}

int result = k % modbase;

결과는 여전히 동일한 등가 클래스에 있습니다.


1

x = x + m = x - m계수 m.
그래서 -13 = -13 + 64모듈러스 64-13 = 51모듈러스에서 64.
가정 Z = X * d + r하면, 0 < r < X다음 부문에서 Z/X우리가 부르는 r나머지를.
Z % X의 나머지를 반환합니다 Z/X.


1

mod 함수는 숫자가 해당 숫자보다 크지 않은 제수의 가장 큰 정수배를 초과하는 양으로 정의됩니다. 따라서 귀하의 경우

-13 % 64

-13을 초과하지 않는 64의 가장 큰 정수 배수는 -64입니다. 이제 -64에서 -13을 빼면 51이됩니다.-13 - (-64) = -13 + 64 = 51


0

내 버전의 Java JDK 1.8.0_05 -13 % 64 = -13

-13- (int (-13/64)) 즉, 분수 부분을 제거하기 위해 정수로 나누기 캐스트를 수행 한 다음 분자에서 빼면 numerator- (int (numerator / denominator))가 올바른 값을 제공해야합니다. 나머지 및 기호



0

JLS의 섹션 15.17.3에 따르면 "이진 숫자 승격 후 정수인 피연산자에 대한 나머지 연산은 (a / b) * b + (a % b)가 a와 같은 결과 값을 생성합니다.이 ID는 짝수를 유지합니다. 피제수가 해당 유형에 대해 가능한 가장 큰 음의 정수이고 제수가 -1 (나머지 0) 인 특수한 경우입니다. "

도움이 되었기를 바랍니다.


-1

이 경우 Java가 51을 반환한다고 생각하지 않습니다. Mac에서 Java 8을 실행 중입니다.

-13 % 64 = -13

프로그램:

public class Test {
    public static void main(String[] args) {
        int i = -13;
        int j = 64;
        System.out.println(i % j);
    }
}

5
@XaverKapeller, 안돼! 많은 사람들이 수학적으로 말하는 -13과 51이 맞다고 지적했습니다. 자바에서는 -13이 예상되는 대답이고, 나도 얻은 것이므로 제출자가 51을 얻었는지 모르겠습니다. 미스터리입니다. 컨텍스트에 대한 모드 세부 사항은이 질문에 올바르게 대답하는 데 도움이 될 수 있습니다.
Fabyen 2014

@Xaver Kapeller : 51과 -13 둘 다 어떻게 맞을 수 있습니까? 자바는 단지 하나 개의 값을 반환합니다 ..
ceprateek

@XaverKapeller Java가 실제로 잘못되었을 가능성이있는 것을 문서화하는 대답은 어떻게 될 수 있습니까?
Marquis of Lorne

@EJP 3 년 전 제가이 글을 썼을 때 저는 자바가 이것을 어떻게 처리하는지에 대한 단순한 현실보다 수학적 정확성을 더 중요시 할만큼 멍청했습니다. 내 어리석은 댓글을 제거하도록 상기시켜 주셔서 감사합니다. : D
Xaver Kapeller
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.