Java double
dalam format IEEE-754 , oleh karena itu mereka memiliki pecahan 52-bit; antara dua pangkat dua yang berdekatan (termasuk satu dan tidak termasuk pangkat berikutnya), oleh karena itu akan ada 2 pangkat 52 yang berbeda double
(yaitu, 4503599627370496 di antaranya). Misalnya, itu adalah jumlah perbedaan double
antara 0,5 yang disertakan dan 1,0 yang dikecualikan, dan banyak juga yang berada di antara 1,0 yang disertakan dan 2,0 yang dikecualikan, dan seterusnya.
Menghitung doubles
antara 0,0 dan 1,0 lebih sulit daripada melakukannya di antara pangkat dua, karena ada banyak pangkat dua yang termasuk dalam kisaran itu, dan, juga, seseorang akan mengalami masalah pelik tentang bilangan yang dinormalisasi. 10 dari 11 bit eksponen mencakup kisaran yang dimaksud, jadi, termasuk angka yang didenormalisasi (dan saya pikir beberapa jenis NaN
) Anda akan memiliki 1024 kali double
s seperti yang berada di antara pangkat dua - tidak lebih dari 2**62
totalnya . Tidak termasuk dinormalisasi & c, saya yakin jumlahnya akan menjadi 1023 kali 2**52
.
Untuk rentang arbitrer seperti "100 hingga 100.1", ini lebih sulit karena batas atas tidak dapat secara tepat direpresentasikan sebagai double
(bukan kelipatan tepat dari pangkat dua). Sebagai perkiraan praktis, karena progresi antara pangkat dua adalah linier, Anda dapat mengatakan bahwa rentang tersebut adalah 0.1 / 64
rentang antara pangkat dua di sekitarnya (64 dan 128), jadi Anda akan mengharapkan
(0.1 / 64) * 2**52
berbeda double
s - yang datang ke 7036874417766.4004
... memberi atau menerima satu atau dua ;-).
2**64
menjelaskan ini: tidak ada lebih dari kemungkinan nilai ganda (karena ini adalah tipe 64 bit), dan tampaknya proporsi BESAR dari nilai-nilai itu ada di antara0..1
?Setiap
double
nilai yang representasi berada di antara0x0000000000000000
dan0x3ff0000000000000
terletak di interval [0,0, 1,0]. Itu (2 ^ 62 - 2 ^ 52) nilai yang berbeda (plus atau minus pasangan tergantung pada apakah Anda menghitung titik akhir).Interval [1.0, 2.0] sesuai dengan representasi antara
0x3ff0000000000000
dan0x400000000000000
; itu 2 ^ 52 nilai yang berbeda.Interval [100.0, 101.0] sesuai dengan representasi antara
0x4059000000000000
dan0x4059400000000000
; itu 2 ^ 46 nilai yang berbeda.Tidak ada penggandaan antara 10 ^ 100 dan 10 ^ 100 + 1 . Tidak ada satu pun dari angka-angka itu yang dapat diwakili dalam presisi ganda, dan tidak ada angka ganda yang berada di antara keduanya. Dua angka presisi ganda terdekat adalah:
dan
sumber
Orang lain telah menjelaskan bahwa ada sekitar 2 ^ 62 ganda dalam kisaran [0,0, 1,0].
(Tidak benar-benar mengejutkan: ada hampir 2 ^ 64 ganda terbatas yang berbeda; dari mereka, setengah positif, dan kira-kira setengah dari orang-orang yang <1.0.)
Tetapi Anda menyebutkan generator angka acak: perhatikan bahwa generator angka acak yang menghasilkan angka antara 0,0 dan 1,0 secara umum tidak dapat menghasilkan semua angka ini; biasanya itu hanya akan menghasilkan angka dalam bentuk n / 2 ^ 53 dengan n sebuah integer (lihat misalnya dokumentasi Java untuk nextDouble ). Jadi biasanya hanya ada sekitar 2 ^ 53 (+/- 1, tergantung pada titik akhir mana yang disertakan) kemungkinan nilai untuk
random()
keluaran. Ini berarti bahwa sebagian besar penggandaan di [0,0, 1,0] tidak akan pernah dihasilkan.sumber
Artikel matematika baru Java, Bagian 2: Angka floating-point dari IBM menawarkan potongan kode berikut untuk menyelesaikan ini (dalam float, tetapi saya curiga itu berfungsi untuk ganda juga):
Mereka punya komentar tentang itu:
sumber
float
, notdouble
-float
s memiliki nilai pecahan 23 bit, jadi2**23 -> 8388608
nilai yang berbeda antara pangkat dua yang berdekatan (bagian "inklusif" tentu saja berarti Anda harus menghitung satu lagi, pangkat dua berikutnya).double
s memiliki pecahan 52-bit!double
padanannya dan berpikir "Hei, saya akan menjawab pertanyaan saya sendiri dalam waktu sekitar 5 menit ..."double
dua kekuatan yang berdekatan akan memakan waktu sekitar 52 hari (println
tentu saja akan sangat tidak mungkin untuk berjalan secepat itu apa pun yang terjadi, jadi mari kita asumsikan bahwa satu pernyataan hilang ;-). Saya pikir itu layak untuk mengambil satu tahun atau kurang pada mesin yang kuat tapi realistis ;-).Lihat artikel wikipedia untuk informasi lebih lanjut.
sumber
1
ini salah karena agak tersembunyi selalu satu - karena itu,2^52
, tidak2^53
berbeda nilai-nilai (antara kekuatan yang berdekatan dari dua, satu disertakan dan yang berikutnya dikecualikan - tidak ! Antara 0,0 dan 1,0).Ganda Java adalah nomor binary64 IEEE 754.
Artinya kita perlu mempertimbangkan:
Ini pada dasarnya berarti ada total 2 ^ 62-2 ^ 52 + 1 kemungkinan representasi ganda yang menurut standar adalah antara 0 dan 1. Perhatikan bahwa 2 ^ 52 + 1 adalah untuk menghapus kasus non-normalisasi nomor.
Ingatlah bahwa jika mantissa positif tetapi eksponen negatif, bilangan positif tetapi kurang dari 1 :-)
Untuk bilangan lain sedikit lebih sulit karena bilangan bulat tepi mungkin tidak dapat direpresentasikan secara tepat dalam representasi IEEE 754, dan karena ada bit lain yang digunakan dalam eksponen untuk dapat mewakili bilangan tersebut, jadi semakin besar angkanya semakin rendah nilai-nilai yang berbeda.
sumber