Nilai i untuk (i == -i && i! = 0) mengembalikan true di Java


101

Saya memiliki ifkondisi berikut .

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

Berapa nilai yang iakan dikembalikan trueuntuk kondisi ini di Jawa?

Saya tidak dapat memikirkan nilai seperti itu untuk imempertimbangkan notasi pelengkap dua di Jawa.

Saya juga ingin memiliki bukti aljabar dari jawaban apa pun yang dimiliki kondisi ini (dalam konteks Jawa)?


2
bagaimana jika (i! = null)
zxc

4
Perhatikan itu -0.0juga== 0
Peter Lawrey

2
tulislah sebagaiif(i && i == -i)
Grijesh Chauhan

10
@GrijeshChauhan Di Jawa? Apakah kamu yakin
Denys Séguret

3
@harold Saya telah bertanya dalam wawancara berkali-kali dalam empat tahun terakhir dan hanya sedikit orang yang benar-benar mengerti bahkan dengan petunjuk.
Peter Lawrey

Jawaban:


126

Satu-satunya intnilai yang berhasil adalah Integer.MIN_VALUE.

Itu karena bilangan bulat dinegasikan menggunakan dua cara komplemen .

Menggunakan

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

Anda melihat bahwa Integer.MIN_VALUEadalah

10000000000000000000000000000000

Mengambil nilai negatif dilakukan dengan menukar 0dan 1, yang memberi

01111111111111111111111111111111

dan dengan menambahkan 1, yang memberi

10000000000000000000000000000000

Seperti yang Anda lihat di tautan yang saya berikan, Wikipedia menyebutkan masalah dengan angka paling negatif dan menetapkan itu satu-satunya pengecualian:

Angka paling negatif dalam komplemen dua kadang-kadang disebut "angka ganjil", karena ini adalah satu-satunya pengecualian.

Tentu Anda memiliki fenomena yang sama Long.Min_Valuejika Anda menyimpannya dalam longvariabel.

Perhatikan bahwa ini hanya karena pilihan yang dibuat terkait dengan penyimpanan biner int di Java . Solusi lain (buruk) misalnya dapat meniadakan hanya dengan mengubah bit paling signifikan dan membiarkan bit lain tidak berubah, ini akan menghindari masalah ini dengan MIN_VALUE tetapi akan membuat 2 0nilai berbeda dan aritmatika biner rumit (bagaimana Anda akan melakukannya bertambah misalnya?).


2
Perlu dicatat bahwa komputer biner awal memang menggunakan implementasi tanda dan besaran untuk bilangan bulat yang dijelaskan di paragraf terakhir Anda; seperti halnya angka floating point IEE754. en.wikipedia.org/wiki/…
Dan Is Fiddling By Firelight

1
Re: "ini hanya terkait dengan pilihan yang dibuat mengenai penyimpanan biner ints": Dan pilihan bagaimana menangani overflow. Aturan yang digunakan Java tidak sama dengan aturan yang digunakan oleh (katakanlah) C atau aturan yang digunakan oleh (katakanlah) Standar ML, meskipun semua ini berjalan pada berbagai macam sistem.
ruakh

2
Perlu disebutkan bahwa ini didokumentasikan pada Spesifikasi Java : "Bahasa pemrograman Java menggunakan representasi komplemen dua untuk bilangan bulat, dan kisaran nilai komplemen dua tidak simetris, jadi negasi dari int negatif maksimum atau panjang menghasilkan maksimum yang sama angka negatif."
chesterbr

25

Nilai yang Anda cari adalah Integer.MIN_VALUE.


Saya juga ingin memiliki bukti aljabar dari jawaban apa pun yang dimiliki kondisi ini (dalam konteks dengan java)?

Itu di luar topik untuk Stack Exchange. Tapi Anda bisa melakukannya mulai dari definisi integer Java ( JLS 4.2 )

"Tipe integralnya adalah byte, short, int, dan long, yang nilainya 8-bit, 16-bit, 32-bit dan 64-bit, dua komplemen integer ..."

dan

"Nilai jenis integral adalah bilangan bulat dalam rentang berikut ... Untuk int, dari -2147483648 hingga 2147483647, inklusif"

dan definisi operator Java unary '-' ( JLS 15.15.4 ):

"Untuk nilai bilangan bulat, negasi sama dengan pengurangan dari nol. Bahasa pemrograman Java menggunakan representasi komplemen dua untuk bilangan bulat, dan rentang nilai komplemen dua tidak simetris, jadi negasi dari int negatif maksimum atau panjang menghasilkan hasil yang angka negatif maksimum yang sama. Kelebihan terjadi dalam kasus ini, tetapi tidak ada pengecualian yang terjadi. Untuk semua nilai bilangan bulat x, -x sama dengan (~ x) +1. "


3
Long.MIN_VALUE juga.
Juvanis

1
yang mana 100000 .., dan jika saya mendapat pujian 2, lagi-lagi 011111 ... + 1 = 100000 ... tetapi Anda tahu itu di atas kepala Anda atau kami dapat menerapkan logika apa pun?
Cerah

1
Seperti yang telah saya baca .. aritmatika int java adalah mod aritmatika 2power32, jadi saya berpikir jika kita dapat membuktikan nilai ini hanya dalam 1 atau 2 baris .. jika itu bukti yang besar .. maka tidak ada masalah.
Cerah

2
@Sunny tidak terlalu sulit untuk dibuktikan. Dalam rentang bilangan bulat, semua bilangan positif memiliki pasangan negatif (jadi i != -i). Itu menyisakan dua angka dalam kisaran: 0dan Integer.MIN_VALUE. Karena i != 0di Anda jika, hanya MIN_VALUEtersisa.
Vincent van der Weele

1
@ Heuster - penalaran itu berhasil ... tetapi itu tergantung pada satu atau dua asumsi yang membutuhkan bukti.
Stephen C

18

Selain jawaban yang diberikan sejauh ini ...

Ada empat nilai secara total

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

Nilai yang dibungkus akan dibuka sehingga nilai tersebut juga benar untuk ekspresi ini.

Catatan: Dokumen Math.abs.

public static int abs (int a)

Mengembalikan nilai absolut dari nilai int. Jika argumen tidak negatif, argumen dikembalikan. Jika argumennya negatif, negasi argumen dikembalikan.

Perhatikan bahwa jika argumen sama dengan nilai Integer.MIN_VALUE, nilai int terwakili yang paling negatif, hasilnya adalah nilai yang sama, yaitu negatif.

dan

publik abs panjang statis (panjang a)

Mengembalikan nilai absolut dari nilai panjang. Jika argumen tidak negatif, argumen dikembalikan. Jika argumennya negatif, negasi argumen dikembalikan.

Perhatikan bahwa jika argumen sama dengan nilai Long.MIN_VALUE, nilai panjang terwakili paling negatif, hasilnya adalah nilai yang sama, yaitu negatif.

Mengejutkan bahwa Math.abs mungkin mengembalikan angka negatif. Ini terjadi karena a) tidak ada nilai positif untuk -MIN_VALUE dalam kasus ini b) menjalankan -hasil kalkulasi dalam luapan.

Yang juga menarik adalah mengapa Byte.MIN_VALUE, Short.MIN_VALUE tidak melakukan ini. Ini karena -perubahan tipe intuntuk ini dan dengan demikian tidak ada luapan.

Character.MIN_VALUE tidak bermasalah karena 0.

Float.MIN_VALUE dan Double.MIN_VALUE memiliki arti yang berbeda. Ini adalah nilai terkecil yang dapat direpresentasikan yang lebih besar dari nol. Dengan demikian mereka memiliki nilai negatif yang valid yang bukan dirinya sendiri.


1
Saya ingin tahu tentang Byte.MIN_VALUE dan kemungkinan lainnya, jawaban Anda menyediakannya. Terima kasih
Cengiz Can

14

Seperti yang telah disebutkan orang lain, ini hanya dipenuhi oleh Integer.MIN_VALUE. Sebagai bukti, izinkan saya menawarkan penjelasan yang lebih mudah dipahami selain dalam biner (meskipun masih berakar pada itu).

Perhatikan bahwa Integer.MIN_VALUEsama dengan -2^31atau -2147483648dan Integer.MAX_VALUEsama dengan 2^31-1atau 2147483647. -Integer.MIN_VALUEadalah 2^31, yang sekarang terlalu besar untuk sebuah Integer (karena sudah lewat MAX_VALUE) sehingga menyebabkan Integer overflow, membuatnya Integer.MIN_VALUEkembali. Ini satu MIN_VALUE-satunya bilangan bulat yang melakukan ini karena merupakan satu-satunya bilangan tanpa ekivalen negatif selain 0.


2
@dystroy sebenarnya saya sedang mencari penjelasan, menurut Mark, tidak ada nomor seperti +2147483648 dalam kisaran int, jadi tersangka pertama harus nomor ini selain 0. Range -2 ^ n hingga 2 ^ n-1. Jadi tidak ada pasangan positif ke -2 ^ n. Ini hanya nilai int yang mungkin.
Cerah

1
Saya tidak menjelaskan dalam biner karena sudah dicakup oleh orang lain (pada dasarnya int adalah nilai 32-bit itulah sebabnya ia memiliki batasan itu). Selain itu, negatif dari negatif adalah positif, jadi istilah tersebut masih dapat diterapkan.
Tandai M

1
Anehnya di Jawa, nomor tersebut 2147483648mungkin muncul dalam kode sumber hanya dalam satu keadaan: sebagai operan operator minus unary (JLS 3.10.1).
Eric Jablow

6

Bukti aljabar tentatif, menggunakan modulo 2^32aritmatika:

i == -idapat ditulis ulang sebagai 2 * i == 0(menambahkan idi kedua sisi), atau i << 1 == 0.

Persamaan ini memiliki dua solusi bentuk i == 0 >> 1, yaitu 0bdan 10000000000000000000000000000000bdiperoleh dengan menggeser salah satu 0atau 1ke kiri.

Solusinya i == 0dikecualikan, tetap ada solusinya i == 100000000000000000000000000000000b.


0

Mungkin tidak terlalu mendidik, tetapi alih-alih berpikir Anda dapat menjalankan kode ini:

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

untuk melihat bahwa itu tercetak

-2147483648
-2147483648

tanpa batas :)


Bagaimana menurut Anda itu tanpa batas?
JBelter

Karena i <= Integer.MAX_VALUE tidak akan pernah salah
Kuba

1
Ahh sangat benar, saya pikir saya melihat dengan ketat<
JBelter
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.