Javaは負の数値でモジュラス計算をどのように行うのですか?


92

私は係数を間違っていますか?なぜなら、Javaでは-13 % 64評価することになっているから-13です51


102
@Dan静的メインvoidがなくても...コードが表示されます。
Joris Meys、2010

22
-13&64 == -13
Grodriguez

7
どのようにそれはあなたが-13より51 ratehrを取得していますさ。
Raedwald 2014

3
あなたはモジュラスをまったくしていません。Javaにはモジュロ演算子はありません。%剰余演算子です。
ローンの侯爵

3
紛らわしい質問:他の人が言うように、Java 8は-13を出します。どのJavaバージョンを使用したと思われますか?
JanŻankowski2017年

回答:


103

負の数のモジュラスの両方の定義が使用されています。一部の言語は1つの定義を使用し、一部は別の定義を使用しています。

負の入力に対して負の数を取得したい場合は、これを使用できます。

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

同様に、負の入力で負の数を返す言語を使用していて、正の値を好む場合:

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

3
nが負の場合、これはうまく機能しません。Java 7 Lang Spec(セクション15.17.3)の同じ例を使用する場合:(-5)%(-3)= -2。-3を追加しても機能しません。値が正であることを確認したい場合は、nの絶対値を追加する必要があります。
partlov 2014

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
ボヘミアン

71

「数学的に」両方が正しいので:

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

オプションの1つは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
数学的に健全
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;負のaまたはint result = (((-a) % b) + b) % b;正または負のa
Oz Edri 2015年

@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)が次のような結果値を生成しますa。
15.17.2除算演算子/
[...]
整数除算は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
Oz Edri

6

あなたは使うことができます

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

3
@ruslik次のことも実行できます((x % k) + k) % k。(おそらくあなたの方が読みやすいでしょう。)
John Kurlak 2014年

2
@JohnKurlakバージョンは次のように機能します:4%3 = 1 OR 4%-3 = -2 OR -4%3 = 2 OR -4%-3 = -1しかし、ruslikのバージョンは次のように機能します:4%3 = 1 OR 4%-3 = 1 OR -4%3 = -4 OR -4%-3 = 2
ジョシュア

1
@Joschuaこれを指摘してくれてありがとう。私のコードは、モジュラス結果をの範囲では[0, sign(divisor) * divisor)なくの範囲にする場合に役立ちます[0, sign(dividend) * divisor)
John Kurlak

3

あなたの答えはウィキペディアにあります: modulo operation

Javaでは、剰余演算のサインオンは被除数のサインオンと同じであると述べています。残りの除算演算については問題ないので、-13 / 64 = 0であるため、この場合は-13が返されます。-13-0= -13。

編集:申し訳ありませんが、あなたの質問を誤解しています...あなたは正しい、javaは-13を与えるべきです。もっと周囲のコードを提供できますか?


2

負のオペランドを使用するモジュロ演算は、言語の設計者が定義します。言語の設計者は、それを言語の実装に任せ、CPUアーキテクチャに定義を任せる場合があります。

Java言語の定義が見つかりませんでした。
Ishtarに感謝します。剰余演算子の Java言語仕様では、結果の符号は分子の符号と同じであると述べています。


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/Xr残りを呼び出します。
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によれば、「2進数の数値昇格後の整数であるオペランドの剰余演算は、(a / b)* b +(a%b)がaに等しいような結果値を生成します。この同一性は、被除数がその型で可能な最大の大きさの負の整数であり、除数が-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が正しいと多くの人が指摘しました。Javaでは、-13が予想される答えであり、これも私が得たものなので、サブミッターが51を取得した方法がわかりません。それは謎です。コンテキストに関するモードの詳細は、この質問に正しく回答するのに役立ちます。
Fabyen 2014年

@Xaver Kapeller:51と-13の両方を正しくするにはどうすればよいですか?Javaは値を1つだけ返します..
ceprateek

@XaverKapeller Javaが実際に間違っている可能性があることを文書化した回答はどのようにしてできるでしょうか?
ローン侯爵

@EJP 3年前に私がこれを書いたとき、Javaがこれをどのように処理するかという単純な現実よりも数学の正確さを評価するのに十分に馬鹿でした。私の愚かなコメントを削除するように私に思い出させてくれてありがとう:D
Xaver Kapeller
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.