Divisi Int: Mengapa hasil dari 1/3 == 0?

107

Saya menulis kode ini:

public static void main(String[] args) {
    double g = 1 / 3;
    System.out.printf("%.2f", g);
}

Hasilnya adalah 0. Mengapa ini, dan bagaimana cara mengatasi masalah ini?

Tofiq
sumber

Jawaban:

147

Kedua operan (1 dan 3) adalah bilangan bulat, oleh karena itu aritmatika bilangan bulat (pembagian di sini) digunakan. Mendeklarasikan variabel hasil sebagai ganda hanya menyebabkan konversi implisit terjadi setelah pembagian .

Pembagian bilangan bulat tentu saja mengembalikan hasil sebenarnya dari pembagian yang dibulatkan menuju nol. Hasil dari 0.333...demikian dibulatkan menjadi 0 di sini. (Perhatikan bahwa prosesor sebenarnya tidak melakukan pembulatan apa pun, tetapi Anda masih dapat menganggapnya seperti itu.)

Juga, perhatikan bahwa jika kedua operan (angka) diberikan sebagai float; 3.0 dan 1.0, atau bahkan hanya yang pertama , kemudian aritmatika floating-point digunakan, memberi Anda 0.333....

Noldorin
sumber
33
+1 dan selalu membulatkan ke bawah. int i = .99999999set int ke 0. Lebih khusus lagi, ia mengambil bagian integer dan membuang sisanya.
Byron Whitlock
37
Ini membulatkan "menuju nol" yang merupakan "ke bawah" untuk nilai yang lebih besar dari nol. (+0.9 dibulatkan menjadi 0, -0.9 juga dibulatkan menjadi 0.)
Adrian Smith
@Byron: Ya, tepatnya. Saya tidak percaya prosesor benar-benar melakukan pembulatan apa pun, karena pembagian diimplementasikan dengan sangat berbeda, tetapi berguna untuk memikirkannya seperti itu.
Noldorin
15
Tidak, tidak membulatkan: Pemotongan
Basil Bourque
3
@BasilBourque Dalam terminologi java, pembulatanDOWN mengarah ke nol. Pembulatan FLOORmenuju tak terhingga negatif.
Andreas
23

1/3 menggunakan pembagian integer karena kedua sisi adalah bilangan bulat.

Anda membutuhkan setidaknya satu dari mereka untuk menjadi floatatau double.

Jika Anda memasukkan nilai dalam kode sumber seperti pertanyaan Anda, Anda dapat melakukannya 1.0/3; itu 1.0adalah ganda.

Jika Anda mendapatkan nilai dari tempat lain, Anda dapat menggunakan (double)untuk mengubahnya intmenjadi double.

int x = ...;
int y = ...;
double value = ((double) x) / y;
Adrian Smith
sumber
10

Transmisikan secara eksplisit sebagai double

double g = 1.0/3.0

Ini terjadi karena Java menggunakan operasi pembagian integer untuk 1dan 3karena Anda memasukkannya sebagai konstanta integer.

Charlie
sumber
2

kamu harus menggunakan

double g=1.0/3;

atau

double g=1/3.0;

Divisi integer mengembalikan integer.


sumber
2

Karena Anda melakukan pembagian integer.

Seperti yang dikatakan @Noldorin, jika kedua operator adalah bilangan bulat, maka pembagian bilangan bulat akan digunakan.

Hasil 0,3333333 tidak dapat direpresentasikan sebagai bilangan bulat, oleh karena itu hanya bagian bilangan bulat (0) yang ditetapkan ke hasil.

Jika salah satu operator adalah a double/ float, maka aritmatika floating point akan dilakukan. Tetapi Anda akan memiliki masalah yang sama jika Anda melakukannya:

int n = 1.0 / 3.0;
Tom
sumber
1

Karena itu memperlakukan 1 dan 3 sebagai bilangan bulat, oleh karena itu membulatkan hasilnya ke 0, sehingga itu adalah bilangan bulat.

Untuk mendapatkan hasil yang Anda cari, beri tahu java secara eksplisit bahwa jumlahnya berlipat ganda seperti:

double g = 1.0/3.0;
DanielGibbs
sumber
1

Buatlah 1 menjadi float dan divisi float akan digunakan

public static void main(String d[]){
    double g=1f/3;
    System.out.printf("%.2f",g);
}
sblundy.dll
sumber
1

Konversi di JAVA cukup sederhana tetapi membutuhkan pemahaman. Seperti yang dijelaskan di JLS untuk operasi integer :

Jika operator integer selain operator shift memiliki setidaknya satu operand berjenis panjang, maka operasi dilakukan dengan menggunakan presisi 64-bit, dan hasil dari operator numerik berjenis panjang. Jika operan lain tidak panjang, pertama kali diperlebar (§5.1.5) untuk mengetik panjang dengan promosi numerik (§5.6).

Dan contoh selalu merupakan cara terbaik untuk menerjemahkan JLS;)

int + long -> long
int(1) + long(2) + int(3) -> long(1+2) + long(3)

Jika tidak, operasi dilakukan dengan menggunakan presisi 32-bit, dan hasil dari operator numerik adalah tipe int. Jika salah satu operand bukan int, pertama kali dilebarkan untuk mengetik int dengan promosi numerik.

short + int -> int + int -> int

Contoh kecil menggunakan Eclipse untuk menunjukkan bahwa penambahan dua shortpun tidak akan semudah itu:

short s = 1;
s = s + s; <- Compiling error

//possible loss of precision
//  required: short
//  found:    int

Ini akan membutuhkan pengecoran dengan kemungkinan hilangnya presisi.

Hal yang sama berlaku untuk operator floating point

Jika setidaknya salah satu operand ke operator numerik berjenis double, maka operasi dilakukan menggunakan aritmatika floating-point 64-bit, dan hasil dari operator numerik tersebut adalah nilai bertipe double. Jika operan lain bukan double, pertama kali diperlebar (§5.1.5) untuk mengetik double dengan promosi numerik (§5.6).

Jadi promosi dilakukan di float menjadi double.

Dan campuran bilangan bulat dan nilai mengambang menghasilkan nilai mengambang seperti yang dikatakan

Jika setidaknya salah satu operand ke operator biner berjenis floating-point, maka operasi tersebut adalah operasi floating-point, bahkan jika yang lain adalah integral.

Ini berlaku untuk operator biner tetapi tidak untuk "Operator Penugasan" seperti +=

Contoh kerja sederhana sudah cukup untuk membuktikan ini

int i = 1;
i += 1.5f;

Alasannya adalah bahwa ada pemeran implisit yang dilakukan di sini, ini akan dieksekusi seperti

i = (int) i + 1.5f
i = (int) 2.5f
i = 2
AxelH
sumber
1

1 dan 3 adalah kontan integer sehingga Java melakukan pembagian integer yang hasilnya 0. Jika Anda ingin menulis konstanta ganda, Anda harus menulis 1.0dan 3.0.

Mulai ulang
sumber
1

Solusi termudah adalah dengan melakukan ini

double g = ((double) 1 / 3);

Apa yang dilakukannya, karena Anda tidak memasukkan 1.0 / 3.0, adalah memungkinkan Anda mengonversinya secara manual ke tipe data ganda karena Java menganggapnya sebagai divisi Integer, dan itu akan melakukannya bahkan jika itu berarti mempersempit konversi. Inilah yang disebut operator cor.

Ramzi El-Jabali
sumber
1

Saya melakukan ini.

double g = 1.0/3.0;
System.out.printf("%gf", g);

Gunakan .0 saat melakukan kalkulasi ganda atau Java akan menganggap Anda menggunakan Integer. Jika Perhitungan menggunakan sejumlah nilai ganda, maka outputnya akan menjadi nilai ganda. Jika semuanya adalah Integer, maka outputnya adalah Integer.

BendedWills
sumber
0

(1/3) berarti pembagian bilangan bulat, oleh karena itu Anda tidak bisa mendapatkan nilai desimal dari pembagian ini. Untuk mengatasi masalah ini gunakan:

public static void main(String[] args) {
        double g = 1.0 / 3;
        System.out.printf("%.2f", g);
    }
Maruf Hossain
sumber
0
public static void main(String[] args) {
    double g = 1 / 3;
    System.out.printf("%.2f", g);
}

Karena 1 dan 3 adalah int, hasilnya tidak dibulatkan tetapi dipotong. Jadi Anda mengabaikan pecahan dan hanya mengambil keseluruhan.

Untuk menghindari hal ini, miliki setidaknya satu dari angka 1 atau 3 sebagai bentuk desimal 1.0 dan / atau 3.0.

Bek
sumber
0

Coba ini:

public static void main(String[] args) {
    double a = 1.0;
    double b = 3.0;
    double g = a / b;
    System.out.printf(""+ g);
}
Virus Neeraj
sumber
Harap jangan memposting jawaban hanya kode, sertakan penjelasan apa yang dilakukan kode Anda dan bagaimana (dan mengapa) itu menyelesaikan masalah pertanyaan. Juga pertimbangkan bahwa ini adalah pertanyaan berusia 8 tahun yang memiliki jawaban positif, dan apakah jawaban Anda menambah nilai atas jawaban yang ada.
Mark Rotteveel
-1

Lakukan "double g = 1.0 / 3.0;" sebagai gantinya.

Brian Knoblauch
sumber
Cuma penasaran ... ada apa dengan jawaban ini? Saya menggunakan pendekatan ini saat pertama kali mengalami masalah. Penjelasan tentang apa yang salah dengan solusi ini akan sangat dihargai. Terima kasih sebelumnya.
Tn. Port St Joe
@ Mr. PortStJoe Tidak memberikan detail apa pun kepada orang yang mengajukan pertanyaan. Melihat jawaban teratas, kami dapat melihat mereka menjelaskan MENGAPA hal itu terjadi juga. Meskipun jawabannya mungkin secara teknis benar, kegunaannya mungkin dianggap terbatas.
Andrew T Finnell
-1

Banyak orang lain yang gagal menunjukkan masalah sebenarnya:

Sebuah operasi hanya pada integer akan memasukkan hasil operasi ke integer.

Ini berarti bahwa hasil titik mengambang, yang dapat ditampilkan sebagai bilangan bulat, akan dipotong (hilangkan bagian desimal).

Apa casting (typecasting / konversi jenis) yang Anda tanyakan?

Ini bervariasi pada penerapan bahasanya, tetapi Wikipedia memiliki pandangan yang cukup komprehensif, dan itu berbicara tentang paksaan juga, yang merupakan bagian informasi penting dalam menjawab pertanyaan Anda.

http://en.wikipedia.org/wiki/Type_conversion

sova
sumber
Jawaban ini salah. Tidak ada Pengecoran Jenis atau Konversi Jenis yang terlibat dalam devisi semua bilangan bulat seperti 1/2, tidak dalam bahasa target (java). Anda cukup memanggil pembagian integer, yang akan menghasilkan hasil integer. Type Casting hanya karena konversi dari intke a doubleselama penugasan.
YoYo
@YoYo Anda mengatakan 0,5 adalah integer? Saya tidak berpikir begitu, homie.
sova
1
homie ini tidak mengatakan apa-apa tentang 0.5. Sederhananya, di Jawa, 1/2adalah pembagian integer, yang menghasilkan integer nol. Anda dapat menetapkan nol menjadi ganda, itu akan tetap menjadi nol, meskipun menjadi 0.0ganda.
YoYo