Saya telah membaca posting ini nol negatif dan positif .
Untuk pemahaman saya, kode berikut harus memberi true
dan true
sebagai output.
Namun, itu memberi false
dan true
sebagai hasil.
Saya membandingkan nol negatif dengan nol positif.
public class Test {
public static void main(String[] args) {
float f = 0;
float f2 = -f;
Float F = new Float(f);
Float F1 = new Float(f2);
System.out.println(F1.equals(F));
int i = 0;
int i2 = -i;
Integer I = new Integer(i);
Integer I1 = new Integer(i2);
System.out.println(I1.equals(I));
}
}
Mengapa kita memiliki perilaku berbeda untuk 0 untuk Integer
dan Float
?
i
dani2
persis sama. Kemudian ketika Anda membuatInteger
s baru , keduanya membungkus nilai yang sama persis.I1.equals(I)
akan benar.int i = Integer.MIN_VALUE, i2 = -i;
...new
jenis pembungkus di sini. Cukup gunakan, misalnyaInteger i = 0, i2 = -i; System.out.println(i.equals(i2)); Float f1 = 0f, f2 = -f1; System.out.println(f1.equals(f2));
Jawaban:
Ints dan float adalah binatang yang sangat berbeda di Jawa. Ints dikodekan sebagai komplemen dua , yang memiliki nilai 0 tunggal. Float menggunakan IEEE 754 ( varian 32-bit untuk float, dan 64-bit untuk ganda). IEEE 754 agak rumit, tetapi untuk tujuan jawaban ini, Anda hanya perlu tahu bahwa ia memiliki tiga bagian, yang pertama adalah bit tanda. Itu berarti untuk pelampung apa pun, ada varian positif dan negatif¹. Itu termasuk 0, jadi floats sebenarnya memiliki dua nilai "nol", +0 dan -0.
Sebagai tambahan, komplemen kedua yang digunakan int bukan satu-satunya cara untuk menyandikan bilangan bulat dalam ilmu komputer. Ada metode lain, seperti komplemen yang ' , tetapi mereka memiliki kebiasaan - seperti memiliki kedua +0 dan -0 sebagai nilai yang berbeda. ;-)
Saat Anda membandingkan float primitif (dan ganda), Java memperlakukan +0 dan -0 sama. Tetapi ketika Anda kotak mereka, Jawa memperlakukan mereka secara terpisah, seperti yang dijelaskan dalam
Float#equals
. Ini memungkinkan metode equals konsisten denganhashCode
implementasinya (dan jugacompareTo
), yang hanya menggunakan bit float (termasuk nilai yang ditandatangani) dan mendorong mereka apa adanya ke int.Mereka bisa saja memilih beberapa opsi lain untuk equals / hashCode / compareTo, tetapi mereka tidak melakukannya. Saya tidak yakin apa pertimbangan desainnya. Tetapi setidaknya dalam satu hal,
Float#equals
selalu akan menyimpang dari float primitive==
: Dalam primitifNaN != NaN
, tetapi untuk semua objek,o.equals(o)
juga harus benar . Itu artinya jika sudahFloat f = Float.NaN
, makaf.equals(f)
sekalipunf.floatValue() != f.floatValue()
.Values Nilai NaN (bukan angka) memiliki bit tanda, tetapi tidak memiliki arti selain untuk pemesanan, dan Java mengabaikannya (bahkan untuk pemesanan).
sumber
Ini adalah salah satu dari Float sama dengan pengecualian
Mengapa dijelaskan juga:
-0 dan 0 akan direpresentasikan secara berbeda menggunakan bit Float 31:
Ini bukan masalahnya
Integer
sumber
Untuk bilangan bulat, tidak ada perbedaan antara -0 dan 0 untuk bilangan bulat karena menggunakan representasi pujian Twos . Jadi contoh integer Anda
i
dani1
persis sama.Untuk mengapung, ada representasi -0, dan nilainya setara dengan 0, tetapi representasi bit berbeda. Maka Float baru (0f) dan Float baru (-0f) akan memiliki representasi yang berbeda.
Anda dapat melihat perbedaan dalam representasi bit.
Dan jika Anda membiarkan
f
untuk menyatakan-0f
maka itu akan diperlakukan sebagai bilangan bulat, dan Anda tidak akan melihat perbedaan dalam output.sumber
0.0f == -0.0f
. Jadi perilaku yang berbeda hanya ada dijava.lang.Float
.float
, yang sesuai dengan IEEE754 dalam hal ini danjava.lang.Float
, yang tidak. Jadi hanya perbedaan dalam representasi bit tidak cukup untuk menjelaskan hal ini.