Mengapa Math.floor mengembalikan ganda?

104

Javadoc resmi mengatakan bahwa Math.floor()mengembalikan nilai doubleyang "sama dengan bilangan bulat matematika", tetapi mengapa tidak mengembalikan nilai int?

Raibaz
sumber

Jawaban:

80

Menurut Javadoc yang sama:

Jika argumennya adalah NaNatau tak terhingga atau nol positif atau nol negatif, maka hasilnya sama dengan argumen. Tidak bisa melakukan itu dengan int.

Nilai terbesar doublejuga lebih besar dari yang terbesar int, jadi harus a long.

krosenvold.dll
sumber
40
tampaknya tidak konsisten dengan fungsi Math.Round, yang mengembalikan int / long dan menangani kasus khusus dengan cara yang berbeda.
zod
1
Perhatikan Javadoc mengatakan ia mengembalikan "terbesar (terdekat dengan positif tak terhingga) * nilai floating-point * yang kurang dari atau sama dengan argumen dan sama dengan bilangan bulat matematika" . Diberikan nilai x> 2 ^ 53 yang tidak akan sama dengan nilai dengan bagian pecahannya yang terpotong. Mungkin sedikit lebih kecil dari itu.
Jim Garrison
16

Ini untuk ketepatan. Tipe data ganda memiliki mantissa 53 bit. Antara lain itu berarti bahwa dobel dapat mewakili semua keseluruhan hingga 2 ^ 53 tanpa kehilangan presisi.

Jika Anda menyimpan sejumlah besar dalam bilangan bulat, Anda akan mendapatkan luapan. Bilangan bulat hanya memiliki 32 bit.

Mengembalikan bilangan bulat sebagai dobel adalah hal yang benar untuk dilakukan di sini karena ia menawarkan rentang bilangan berguna yang jauh lebih luas daripada bilangan bulat.

Nils Pipenbrinck
sumber
Bisa butuh waktu lama untuk mengatasi nilai-nilai seperti itu, tentu saja. Anda masih harus memikirkan apa yang harus dilakukan dengan ganda> 2 ^ 63.
Jon Skeet
1
@Jon, benar, tetapi itu akan menghasilkan dampak kinerja (tidak ada instruksi konversi dari long menjadi double dalam set instruksi yang saya ketahui). Saya ingin tahu apa yang dilakukan Math.floor dengan ganda> 2 ^ 53 di tempat pertama. Beberapa hasil tidak dapat direpresentasikan.
Nils Pipenbrinck
Tapi kemudian, bentuk pseudo-idiomatik (int) Math.floor (foo), yang muncul juga di javadoc resmi tidak aman karena hasilnya mungkin tidak sesuai dengan int, iya kan? Dan sekali lagi, manakah bentuk yang aman untuk menggunakan Math.floor, karena hasilnya mungkin tidak cocok bahkan untuk waktu yang lama?
Raibaz
10

Orang lain telah memberi tahu Anda alasannya, saya akan memberi tahu Anda cara membulatkan dengan benar mengingat Anda ingin melakukan ini. Jika Anda hanya akan menggunakan bilangan positif, maka Anda dapat menggunakan pernyataan ini:

int a=(int) 1.5;

Namun, (int) selalu membulatkan ke arah 0. Jadi, jika Anda ingin melakukan bilangan negatif:

int a=(int) -1.5; //Equal to -1

Dalam kasus saya, saya tidak ingin melakukan ini. Saya menggunakan kode berikut untuk melakukan pembulatan, dan tampaknya menangani semua kasus edge dengan baik:

private static long floor(double a)
{
    return (int) Math.floor(a);
}
PearsonArtPhoto
sumber
7
Mengapa tidak digunakan (int) Math.floor(a)? Mungkin lebih efisien dan lebih pendek.
Solomon Ucko
@Solomon Ucko alih-alih (int) Math.floor(a)Anda cukup menulis (int) a, jika a positif.
Leo Leontev
3

Apa yang Anda ingin kembalikan jika Anda memberikannya dua kali lipat lebih besar dari int atau panjang terbesar?

(Memang, jika lebih besar dari panjang terbesar, ketepatannya akan rendah - ini mungkin bukan bilangan bulat teoretis terdekat - tetapi meskipun demikian ...)

Jon Skeet
sumber
0

Sama seperti ada pembagian integer dan floating point di Jawa, ada cara integer dan floating point untuk melakukan floor:

double f = Math.floor(x);

atau

int k = (int) x; 

tetapi Anda harus selalu berhati-hati dalam menggunakan floor dengan aritmatika presisi hingga: perhitungan x Anda dapat menghasilkan sesuatu seperti 1,99999999 yang akan diturunkan ke 1, bukan 2 oleh kedua bentuk. Ada banyak algoritme di luar sana yang perlu mengatasi batasan ini untuk menghindari hasil yang salah untuk beberapa nilai masukan.

Pablo
sumber
0

Sehingga kesalahan dan nilai bukan bilangan bulat lainnya dapat mengalir dengan benar melalui serangkaian perhitungan.

Misalnya, jika Anda memberi makan Not a Number (NaN) ke Math.floor, itu akan meneruskannya.

Jika mengembalikan bilangan bulat, ia tidak dapat meneruskan status atau kesalahan ini, dan Anda bisa mendapatkan hasil buruk dari penghitungan sebelumnya yang terlihat bagus tetapi salah setelah pemrosesan lebih lanjut.

Adam Davis
sumber