Java'da true döndürmek için (i == -i && i! = 0) için i değeri


101

Aşağıdaki ifşartım var.

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

Java'da bu durum için hangi değer idönecek true?

Java'da ikinin tümleyen gösterimini idikkate almanın böyle bir değerini düşünemiyorum .

Ayrıca bu koşulun (Java bağlamında) verdiği cevabın cebirsel kanıtına sahip olmayı çok isterim?


2
peki ya eğer (i! = null)
zxc

4
-0.0Ayrıca unutmayın== 0
Peter Lawrey

2
olarak yazif(i && i == -i)
Grijesh Chauhan

10
@GrijeshChauhan In Java? Emin misiniz ?
Denys Séguret

3
@harold Son dört yılda birçok röportajda sordum ve çok az kişi ipuçlarıyla bile anladı.
Peter Lawrey

Yanıtlar:


126

Çalıştığı tek intdeğer Integer.MIN_VALUE.

Bunun nedeni, tam sayıların ikinin tümleyen yolu kullanılarak olumsuzlanmasıdır .

Kullanma

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

Bunu gördünüz Integer.MIN_VALUEolduğunu

10000000000000000000000000000000

Negatif değer alarak ilk-çıkar yapılır 0ve 1verir,

01111111111111111111111111111111

tarafından ekleyerek 1veren

10000000000000000000000000000000

Verdiğim bağlantıda görebileceğiniz gibi, Wikipedia sorundan en negatif sayılarla bahsediyor ve bunun tek istisna olduğunu belirtiyor:

İkinin tümleyenindeki en negatif sayı bazen "tuhaf sayı" olarak adlandırılır çünkü tek istisnadır.

Elbette Long.Min_Value, bir longdeğişkende saklarsanız aynı fenomene sahip olursunuz .

Bunun yalnızca Java'da ints'in ikili olarak depolanmasıyla ilgili yapılan seçimlerden kaynaklandığını unutmayın . Başka bir (kötü) çözüm, örneğin en önemli biti değiştirerek ve diğer bitleri değiştirmeden bırakarak olumsuzlamak olabilirdi, bu, MIN_VALUE ile bu sorunu önleyebilirdi, ancak 2 farklı 0değer ve karmaşık ikili aritmetik (nasıl olurdu? örneğin artırılmış?).


2
İlk ikili bilgisayarların, son paragrafınızda açıklanan tamsayılar için işaret ve büyüklük uygulamasını kullandığını belirtmek gerekir; IEE754 kayan noktalı sayılar gibi. en.wikipedia.org/wiki/…
Dan Is Fiddling By Firelight

1
Ynt: "Bu yalnızca, int'lerin ikili depolanması ile ilgili yapılan seçimlerle ilgilidir": Ve taşmanın nasıl ele alınacağına ilişkin seçimler. Java'nın kullandığı kural (örneğin) C tarafından kullanılan kural veya (örneğin) Standart ML tarafından kullanılan kural ile aynı değildir, ancak bunların tümü çok çeşitli sistemlerde çalışmaktadır.
ruakh

2
Java Spesifikasyonunda belgelendiğinden bahsetmeye değer : "Java programlama dili, tamsayılar için ikinin tamamlayıcı gösterimini kullanır ve ikinin tamamlayıcı değerlerinin aralığı simetrik değildir, bu nedenle maksimum negatif int veya uzun sonuçların aynı maksimumda olumsuzlanması negatif sayı. "
chesterbr

25

Aradığınız değer Integer.MIN_VALUE.


Ayrıca bu koşulun (java bağlamında) verdiği cevabın cebirsel kanıtına sahip olmayı çok isterim?

Bu, Stack Exchange için konu dışı. Ancak bunu Java tamsayılarının tanımından başlayarak yapabilirsiniz ( JLS 4.2 )

"İntegral türleri, değerleri 8-bit, 16-bit, 32-bit ve 64-bit işaretli ikinin tamamlayıcı tamsayıları olan bayt, kısa, int ve uzun şeklindedir ..."

ve

"İntegral türlerinin değerleri aşağıdaki aralıklarda bulunan tam sayılardır ... int için, -2147483648 ile 2147483647 arası, dahil"

ve Java tekli '-' operatörünün tanımı ( JLS 15.15.4 ):

"Tamsayı değerleri için olumsuzlama, sıfırdan çıkarma ile aynıdır. Java programlama dili, tamsayılar için ikinin tamamlayıcı gösterimini kullanır ve ikinin tamamlayıcı değerlerinin aralığı simetrik değildir, bu nedenle maksimum negatif int veya uzun sonuçların olumsuzlanması bunda aynı maksimum negatif sayı. Bu durumda taşma meydana gelir, ancak bir istisna atılmaz. Tüm tam sayı değerleri için x, -x eşittir (~ x) +1. "


3
Long.MIN_VALUE da.
Juvanis

1
ki bu 100000 .. ve eğer 2'nin iltifatını alırsam, yine 011111 ... + 1 = 100000 ... ama bunu biliyorsun ya da herhangi bir mantık uygulayabilir miyiz?
Güneşli

1
Okuduğum gibi ... java'nın int aritmetiği aritmetik mod 2power32, bu yüzden bu değeri sadece 1 veya 2 satırda ispatlayabilir miyiz diye düşünüyordum .. büyük bir kanıtıysa .. o zaman sorun yok.
Güneşli

2
@Sunny kanıtlamak çok zor olamaz. Tamsayı aralığında, tüm pozitif sayıların negatif bir karşılığı vardır (yani i != -i). Bu, aralıkta iki sayı bırakır: 0ve Integer.MIN_VALUE. Çünkü i != 0senin içinde, sadece MIN_VALUEkaldı.
Vincent van der Weele

1
@Heuster - bu akıl yürütme işe yarar ... ancak kanıt gerektiren bir veya iki varsayıma bağlıdır.
Stephen C

18

Şimdiye kadar verilen cevaplara ek olarak ...

Toplamda dört değer var

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

Sarılmış değerler sarmalanmaz, dolayısıyla bu ifade için de geçerlidir.

Not: Math.abs belgeleri.

public static int abs (int a)

Bir int değerinin mutlak değerini döndürür. Argüman negatif değilse, argüman döndürülür. Bağımsız değişken negatifse, bağımsız değişkenin olumsuzluğu döndürülür.

Bağımsız değişken, gösterilebilir en negatif int değeri olan Tamsayı.MIN_VALUE değerine eşitse, sonuç negatif olan aynı değerdir.

ve

public statik uzun abs (uzun a)

Uzun bir değerin mutlak değerini döndürür. Argüman negatif değilse, argüman döndürülür. Bağımsız değişken negatifse, bağımsız değişkenin olumsuzluğu döndürülür.

Bağımsız değişken, gösterilebilir en negatif uzun değer olan Long.MIN_VALUE değerine eşitse, sonuç negatif olan aynı değerdir.

Math.abs'ın negatif bir sayı döndürmesi şaşırtıcıdır. Bunun nedeni, a) bu durumlarda -MIN_VALUE için pozitif değerler olmaması, b) -hesaplama sonuçlarının bir taşma ile gerçekleştirilmesi.

Ayrıca ilginç olan, Byte.MIN_VALUE, Short.MIN_VALUE'nun neden bunu yapmadığıdır. Bunun nedeni, -tipin intbunlar için değiştirilmesidir ve dolayısıyla taşma olmamasıdır.

Karakter.MIN_VALUE, 0 olduğu için problem yaşamıyor.

Float.MIN_VALUE ve Double.MIN_VALUE farklı bir anlama sahiptir. Bunlar, sıfırdan büyük temsil edilebilen en küçük değerdir. Böylece kendileri olmayan geçerli negatif değerlere sahiptirler.


1
Byte.MIN_VALUE ve diğer olasılıkları merak ediyordum, cevabınız bunu sağladı. Teşekkürler
Cengiz Can 13

14

Diğerlerinin de bahsettiği gibi, bu sadece yerine getirilir Integer.MIN_VALUE. Kanıta gelince, ikiliden başka anlaşılması daha kolay bir açıklama sunmama izin verin (yine de bu konuya kök salmış olsa da).

Not Integer.MIN_VALUEeşittir -2^31ya -2147483648ve Integer.MAX_VALUEeşit olduğu 2^31-1ya da 2147483647. -Integer.MIN_VALUEolduğu 2^31(geçmiş olduğundan artık bir tamsayı için çok büyük olan MAX_VALUE) böylece yapma, bir tamsayı taşması neden Integer.MIN_VALUEtekrar. Bunu yapan tek Tamsayıdır çünkü MIN_VALUE0'dan başka negatif eşdeğeri olmayan tek sayıdır.


2
@dystroy aslında Mark'a göre bir açıklama arıyordum, int aralığında +2147483648 gibi bir sayı yok, bu yüzden ilk şüpheli 0'dan başka bu sayı olmalı. Aralık -2 ^ n ila 2 ^ n-1. Yani -2 ^ n'nin pozitif bir karşılığı yoktur. Bu yalnızca başka bir olası int değeridir.
Güneşli

1
Zaten bir başkası tarafından kapsanmış olduğu için ikili olarak açıklamadım (temelde int 32 bitlik bir değerdir, bu yüzden bu limitlere sahiptir). Ayrıca, negatifin negatifi pozitiftir, bu nedenle terimler yine de geçerli olabilir.
Mark M

1
İşin garibi Java'da, sayı 2147483648yalnızca bir durumda kaynak kodunda görünebilir: tekli eksi operatörün işlenen olarak (JLS 3.10.1).
Eric Jablow

6

modulo 2^32Aritmetik kullanarak geçici cebirsel kanıt :

i == -iolarak yeniden yazılabilir 2 * i == 0( iher iki tarafa ekleyerek ) veya i << 1 == 0.

Bu denklemin iki form çözümü vardır i == 0 >> 1, yani 0bve sola veya sağa 10000000000000000000000000000000bkaydırarak elde edilir .01

Çözüm i == 0dışarıda bırakıldığında, çözüm orada kalır i == 100000000000000000000000000000000b.


0

Belki çok eğitici değildir, ancak düşünmek yerine şu kodu çalıştırabilirsiniz:

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

yazdırdığını görmek için

-2147483648
-2147483648

sonsuz :)


Sonsuz olduğunu nasıl anlarsınız?
JBelter

Çünkü i <= Tamsayı.MAX_VALUE asla yanlış olmayacak
Kuba

1
Ahh çok doğru, kesinlikle gördüğümü sanıyordum<
JBelter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.