Javaでtrueを返す(i == -i && i!= 0)のiの値


101

以下のif状態です。

if (i == -i && i != 0)

Javaでこの条件に対してどのような値iが返さtrueれますか?

私は、Javaで2の補数表記をi考慮することのそのような価値を考えることができません。

私はまた、この条件が(Javaとの関連で)持っているすべての答えを代数的に証明したいと思いますか?


2
if(i!= null)
zxc 2013

4
それ-0.0もあることに注意してください== 0
ピーター・ローレイ2013

2
それを次のように書いてくださいif(i && i == -i)
Grijesh Chauhan 2013

10
@GrijeshChauhan in Java?本気ですか ?
DenysSéguret2013

3
@harold私は過去4年間に何度もインタビューで質問してきましたが、ほんの少しでも実際にそれを理解できる人はほとんどいません。
Peter Lawrey 2013

回答:


126

機能する唯一のint値は Integer.MIN_VALUEです。

これは、整数が2の補数の方法を使用して否定されるためです。

使用する

System.out.println(Integer.toBinaryString(Integer.MIN_VALUE));

あなたはそれが見Integer.MIN_VALUEています

10000000000000000000000000000000

負の値をとるが最初スワッピングによって行われる01、与えます

01111111111111111111111111111111

を追加すると1

10000000000000000000000000000000

あなたが私が与えたリンクで見ることができるように、ウィキペディアは最も負の数の問題に言及し、それが唯一の例外であることを指定します:

2の補数で最も負の数は、唯一の例外であるため、「奇妙な数」と呼ばれることもあります。

もちろんLong.Min_Valuelong変数に格納した場合と同じ現象があります。

これは、Javaのintのバイナリストレージに関する選択が原因であることに注意してください。別の(悪い)解決策は、たとえば最上位ビットを変更して他のビットを変更しないことで否定することでした。これにより、MIN_VALUEでこの問題は回避されましたが、2つの異なる0値と複雑なバイナリ演算が行われました(どのようにたとえば、増分されますか?)。


2
初期のバイナリコンピュータは、前の段落で説明した整数の符号と絶対値の実装を使用していたことは注目に値します。IEE754浮動小数点数と同様に。 en.wikipedia.org/wiki/...
ダンであるいじることで火明かり

1
再:「これは整数のバイナリストレージに関して行われた選択にのみ関連しています」:オーバーフローを処理する方法の選択。Javaが使用するルールは、Cなどが使用するルールや標準MLが使用するルールとは異なりますが、これらはすべて、さまざまなシステムで実行されます。
ruakh 2013

2
Java仕様に記載されていることに言及する価値があります:「Javaプログラミング言語は整数の2の補数表現を使用し、2の補数の値の範囲は対称ではないため、最大の負のintまたはlongの否定は同じ最大になります負の数。"
chesterbr 2013

25

あなたが探している値はInteger.MIN_VALUEです。


私はまた、この条件が持っているすべての答えを代数的に証明したいと思います(Javaとの関連で)?

これはStack Exchangeのトピックから外れています。しかし、Java整数の定義(JLS 4.2)から始めることができます。

「整数型は、バイト、ショート、整数、およびロングで、その値は8ビット、16ビット、32ビット、および64ビットの符号付き2の補数の整数です...」

そして

「整数型の値は、次の範囲の整数です... intの場合、-2147483648から2147483647まで。

Javaの単項「-」演算子の定義(JLS 15.15.4):

「整数値の場合、否定はゼロからの減算と同じです。Javaプログラミング言語は整数の2の補数表現を使用し、2の補数の値の範囲は対称的ではないため、最大の負のintまたはlongの否定はその結果になります同じ最大負数。この場合、オーバーフローが発生しますが、例外はスローされません。すべての整数値xについて、-xは(〜x)+1と等しくなります。


3
Long.MIN_VALUEも。
Juvanis 2013

1
これは100000です。2の褒め言葉を受け取った場合、これも011111 ... + 1 = 100000 ...ですが、頭の上にあるか、ロジックを適用できますか?
サニー

1
私が読んだように..javaのint演算は算術mod 2power32なので、この値を1行または2行で証明できるかどうかを考えていました。大きな証明であれば、問題はありません。
2013

2
@Sunny証明するのは難しいことではありません。整数の範囲では、すべての正の数に負の対応(so i != -i)があります。その葉2つの範囲内の数字:0Integer.MIN_VALUEi != 0あなたの為に、MIN_VALUE残っているだけです。
Vincent van der Weele 2013

1
@Heuster-その推論は機能します...しかし、それは証明を必要とする1つまたは2つの仮定に依存します。
スティーブンC

18

これまでの回答に加えて...

合計4つの値があります

int i = Integer.MIN_VALUE;
long i = Long.MIN_VALUE;
Integer i = Integer.valueOf(Integer.MIN_VALUE);
Long i = Long.valueOf(Long.MIN_VALUE);

ラップされた値はラップ解除されるため、この式でも真になります。

注:Math.absドキュメント。

パブリック静的int abs(int a)

int値の絶対値を返します。引数が負でない場合、引数が返されます。引数が負の場合、引数の否定が返されます。

引数がInteger.MIN_VALUEの値と等しい場合、表現可能な最も負のint値である場合、結果は同じ値、つまり負になります。

そして

public static long abs(long a)

long値の絶対値を返します。引数が負でない場合、引数が返されます。引数が負の場合、引数の否定が返されます。

引数がLong.MIN_VALUEの値(最も負の表現可能なlong値)と等しい場合、結果は同じ値(負)になることに注意してください。

Math.absが負の数を返すのは驚くべきことです。これは、a)これらのケースでは-MIN_VALUEに正の値がないため、b)-オーバーフローで計算結果を実行するために発生します。

また興味深いのは、Byte.MIN_VALUE、Short.MIN_VALUEがこれを行わない理由です。これは、-intこれらのタイプをに変更し、オーバーフローしないためです。

Character.MIN_VALUEは0なので問題ありません。

Float.MIN_VALUEとDouble.MIN_VALUEの意味は異なります。これらは、ゼロより大きい最小の表現可能な値です。したがって、それらには有効な負の値があり、それ自体ではありません。


1
Byte.MIN_VALUEと他の可能性について疑問に思っていましたが、あなたの答えはそれを提供しました。ありがとう
Cengizは2013

14

他の人が述べたように、これはによってのみ満たされInteger.MIN_VALUEます。証明については、バイナリ以外の方がわかりやすい説明を提供させていただきます(それはまだ根ざしていますが)。

音符Integer.MIN_VALUEに等しい-2^31又は-2147483648且つInteger.MAX_VALUEに等しいです2^31-1か、2147483647-Integer.MIN_VALUEis 2^31であり、これは(大きすぎるため)Integerには大きすぎるためMAX_VALUE、Integerオーバーフローを引き起こし、Integer.MIN_VALUE再びそれを作ります。MIN_VALUE0以外に負の同等値がない唯一の数値であるため、これを行うのは唯一の整数です。


2
@dystroyは実際に説明を探していました。Markによると、intの範囲には+2147483648のような番号はないため、最初の容疑者は0以外のこの番号である必要があります。範囲は-2 ^ nから2 ^ n-1です。したがって、-2 ^ nに対応する正の値はありません。これは、考えられるもう1つのint値にすぎません。
サニー

1
他の誰かによってすでにカバーされているので、バイナリでは説明しませんでした(基本的にintは32ビット値であり、そのためにこれらの制限があります)。また、ネガティブのネガティブはポジティブなので、条件は引き続き適用できます。
マークM

1
奇妙なことにJavaでは、この数値2147483648はソースコードに次の1つの状況でのみ現れることがあります。単項マイナス演算子(JLS 3.10.1)のオペランドとして。
Eric Jablow 2013

6

modulo 2^32算術を使用した仮の代数証明:

i == -i2 * i == 0i両側に追加)またはとして書き換えられi << 1 == 0ます。

この方程式は、フォームの二つの溶液を有しi == 0 >> 1、すなわち、0b10000000000000000000000000000000bのいずれかにシフトすることによって得られた0又は1左側に。

ソリューションi == 0が除外されているため、ソリューションが残っていますi == 100000000000000000000000000000000b


0

あまり教育的ではないかもしれませんが、考えずにこのコードを実行することができます。

    for (int i = Integer.MIN_VALUE; i <= Integer.MAX_VALUE; i++)
    {
        if (i == -i && i != 0)
        {
            System.out.println(i);
        }
    }

印刷されることを確認するには

-2147483648
-2147483648

無限に:)


それが無限にあるとどう思いますか?
JBelter 2013

i <= Integer.MAX_VALUEがfalseになることはないため
Kuba

1
ああ非常に真実、私が厳密に見たと思った<
JBelter 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.