Divisi integer: Bagaimana Anda menghasilkan ganda?


249

Untuk blok kode ini:

int num = 5;
int denom = 7;
double d = num / denom;

nilai dis 0.0. Itu bisa dipaksa untuk bekerja dengan casting:

double d = ((double) num) / denom;

Tetapi apakah ada cara lain untuk mendapatkan doublehasil yang benar ? Saya tidak suka casting primitif, siapa yang tahu apa yang mungkin terjadi.



9
casting 'int' ke dobel aman, Anda akan selalu mendapatkan nilai yang sama tanpa kehilangan presisi.
Peter Lawrey

1
Saya ingin tahu apakah berikut ini adalah langkah-langkah yang benar yang diambil oleh kompiler untuk divisi: 1) melemparkan num ke float 2) melemparkan denom ke float juga 2) membagi num dengan denom. Tolong beri tahu saya jika saya salah.
mannyee

Jawaban:


156
double num = 5;

Itu menghindari gips. Tetapi Anda akan menemukan bahwa konversi pemeran didefinisikan dengan baik. Anda tidak perlu menebak, cukup periksa JLS . int to double adalah konversi pelebaran. Dari §5.1.2 :

Pelebaran konversi primitif tidak kehilangan informasi tentang besarnya keseluruhan nilai numerik.

[...]

Konversi int atau nilai panjang menjadi float, atau nilai panjang menjadi dua kali lipat, dapat mengakibatkan hilangnya presisi — yaitu, hasilnya mungkin kehilangan beberapa bit nilai yang paling tidak signifikan. Dalam hal ini, nilai floating-point yang dihasilkan akan menjadi versi bulat dari nilai integer, menggunakan IEEE 754 round-to-terdekat mode (§4.2.4) .

5 dapat diekspresikan tepat sebagai ganda.


60
+1. Berhentilah takut casting. Pelajari cara kerjanya. Semuanya didefinisikan dengan baik.
Mark Peters

1
@FabricioPH Ini berfungsi di setiap situasi, dan identik dengan solusi * 1.0.
Vitruvius

3
@ Saposhiente Ini melampaui bekerja atau tidak. Mengubah jenis variabel tampaknya kode kotor bagi saya. Jika Anda memiliki sesuatu yang HARUS menjadi bilangan bulat dan Anda mengubah representasi untuk float hanya untuk dapat melakukan operasi matematika, Anda mungkin mempertaruhkan diri sendiri. Juga dalam beberapa konteks membaca variabel sebagai integer membuat kode lebih mudah dipahami.
Fabricio PH

2
@FabricioPH, mengalikan dengan 1.0masih mengubah jenis hasilnya, hanya dengan cara yang berbeda. 'Sepertinya kode kotor bagi saya' tidak menjelaskan dalam skenario apa Anda yakin mengalikan dengan 1.0sebenarnya lebih baik (atau mengapa itu mungkin).
Matthew Flaschen

4
@FabricioPH Anda dan OP tampaknya bekerja di bawah keyakinan salah (di mana Anda mengatakan "Mengubah jenis variabel") yang melakukan (double)numperubahan entah bagaimana num. Tidak - itu menciptakan dobel sementara untuk konteks pernyataan itu.
Paul Tomblin

100

Apa yang salah dengan casting primitif?

Jika Anda tidak ingin melakukan casting karena alasan tertentu, Anda bisa melakukannya

double d = num * 1.0 / denom;

63
... yang melakukan pemeran implisit sebelum perkalian
Alice Purcell

2
Dalam kebanyakan kasus ini lebih baik daripada mengubah jenis variabel lainnya.
Fabricio PH

3
@FabricioPH Tidak ada yang menunjukkan ini benar, kecuali jika Anda memiliki sumber untuk mengutip.
Vitruvius

1
@Saposhiente menjawab dalam komentar Anda yang serupa
Fabricio PH

1
Anda juga dapat menggunakan postfix "D" (untuk melakukan cast implisit yang sama); - jadi misalnya:double d = num * 1D / denom;
BrainSlugs83

73

Saya tidak suka casting primitif, siapa yang tahu apa yang mungkin terjadi.

Mengapa Anda memiliki rasa takut yang irasional terhadap pemeran primitif? Tidak ada yang buruk akan terjadi ketika Anda melemparkan intke double. Jika Anda tidak yakin bagaimana cara kerjanya, cari di Spesifikasi Bahasa Jawa . Casting intto to doubleadalah konversi primitif yang melebar .

Anda dapat menyingkirkan pasangan kurung tambahan dengan melemparkan penyebut alih-alih pembilang:

double d = num / (double) denom;

2
Anda juga bisa melakukan double d = (double) num / denom;... (OK, yang ini tergantung pada diutamakan)
user85421

27

Jika Anda mengubah jenis satu variabel Anda harus ingat untuk menyelinap di ganda lagi jika rumus Anda berubah, karena jika variabel ini berhenti menjadi bagian dari perhitungan, hasilnya kacau. Saya membuat kebiasaan casting dalam perhitungan, dan menambahkan komentar di sebelahnya.

double d = 5 / (double) 20; //cast to double, to do floating point calculations

Perhatikan bahwa casting hasilnya tidak akan berhasil

double d = (double)(5 / 20); //produces 0.0

17

Keluarkan salah satu bilangan bulat / kedua bilangan bulat ke float untuk memaksa operasi dilakukan dengan floating point Math. Kalau tidak, bilangan bulat Matematika selalu lebih disukai. Begitu:

1. double d = (double)5 / 20;
2. double v = (double)5 / (double) 20;
3. double v = 5 / (double) 20;

Perhatikan bahwa casting hasilnya tidak akan berhasil. Karena pembagian pertama dilakukan sesuai aturan diutamakan.

double d = (double)(5 / 20); //produces 0.0

Saya tidak berpikir ada masalah dengan casting seperti yang Anda pikirkan.


10

Tipe Casting Adalah Satu-Satunya Cara


Memproduksi doubledari divisi integer - tidak ada cara lain tanpa casting (mungkin Anda tidak akan melakukannya secara eksplisit tetapi itu akan terjadi).

Sekarang, ada beberapa cara kita dapat mencoba untuk mendapatkan yang tepat doublenilai (di mana numdan denomadalah intjenis, dan dari-kursus dengan pengecoran ) -

  1. dengan casting eksplisit:

    • double d = (double) num / denom;
    • double d = ((double) num) / denom;
    • double d = num / (double) denom;
    • double d = (double) num / (double) denom;

tapi tidak double d = (double) (num / denom);

  1. dengan casting implisit:

    • double d = num * 1.0 / denom;
    • double d = num / 1d / denom;
    • double d = ( num + 0.0 ) / denom;
    • double d = num; d /= denom;

tapi tidak double d = num / denom * 1.0;
dan tidakdouble d = 0.0 + ( num / denom );


2

gunakan sesuatu seperti:

double step = 1d / 5;

(1d adalah gips untuk menggandakan)


5
1d bukan gips, itu hanya deklarasi.
Sefier Tang

0

Anda mungkin mempertimbangkan untuk mengakhiri operasi. Sebagai contoh:

class Utils
{
    public static double divide(int num, int denom) {
        return ((double) num) / denom;
    }
}

Ini memungkinkan Anda untuk melihat ke atas (sekali saja) apakah para pemain melakukan apa yang Anda inginkan. Metode ini juga dapat diuji, untuk memastikan bahwa ia terus melakukan apa yang Anda inginkan. Juga tidak masalah trik apa yang Anda gunakan untuk menyebabkan pembagian (Anda bisa menggunakan salah satu jawaban di sini), selama itu menghasilkan hasil yang benar. Di mana pun Anda perlu membagi dua bilangan bulat, Anda sekarang dapat menelepon Utils::dividedan percaya bahwa itu melakukan hal yang benar.



0

Cara terbaik untuk melakukan ini adalah

int i = 3;
Double d = i * 1.0;

d is 3.0 now.
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.