Banyak jawaban dari jaman dulu telah menunjukkan hasil true
dari 9007199254740992 === 9007199254740992 + 1
untuk memverifikasi bahwa 9 007 199 254 740 991 adalah maksimum dan integer aman.
Bagaimana jika kita terus melakukan akumulasi:
input: 9007199254740992 + 1 output: 9007199254740992 // expected: 9007199254740993
input: 9007199254740992 + 2 output: 9007199254740994 // expected: 9007199254740994
input: 9007199254740992 + 3 output: 9007199254740996 // expected: 9007199254740995
input: 9007199254740992 + 4 output: 9007199254740996 // expected: 9007199254740996
Kita bisa mengetahui bahwa di antara angka-angka yang lebih besar dari 9 007 199 254 740 992 , hanya angka genap yang dapat diwakili .
Ini adalah pintu masuk untuk menjelaskan bagaimana format biner 64-bit presisi ganda bekerja pada ini. Mari kita lihat bagaimana 9 007 199 254 740 992 dipegang (diwakili) dengan menggunakan format biner ini.
Menggunakan versi singkat untuk menunjukkannya dari 4 503 599 627 370 496 :
1 . 0000 ---- 0000 * 2^52 => 1 0000 ---- 0000.
|-- 52 bits --| |exponent part| |-- 52 bits --|
Di sisi kiri panah, kita memiliki nilai bit 1 , dan titik radix yang berdekatan , kemudian dengan mengalikan 2^52
, kita memindahkan titik radix 52 langkah ke kanan, dan menuju akhir. Sekarang kita mendapatkan 4503599627370496 dalam bentuk biner.
Sekarang kita mulai mengakumulasi 1 ke nilai ini sampai semua bit diatur ke 1, yang sama dengan 9 007 199 254 740 991 dalam desimal.
1 . 0000 ---- 0000 * 2^52 => 1 0000 ---- 0000.
(+1)
1 . 0000 ---- 0001 * 2^52 => 1 0000 ---- 0001.
(+1)
1 . 0000 ---- 0010 * 2^52 => 1 0000 ---- 0010.
(+1)
.
.
.
1 . 1111 ---- 1111 * 2^52 => 1 1111 ---- 1111.
Sekarang, karena dalam format biner 64-bit presisi ganda , ia secara ketat mengalokasikan 52 bit untuk fraksi, tidak ada lagi bit yang tersedia untuk dibawa untuk menambahkan satu lagi 1, jadi yang bisa kita lakukan adalah mengatur semua bit kembali ke 0, dan memanipulasi bagian eksponen:
|--> This bit is implicit and persistent.
|
1 . 1111 ---- 1111 * 2^52 => 1 1111 ---- 1111.
|-- 52 bits --| |-- 52 bits --|
(+1)
(radix point has no way to go)
1 . 0000 ---- 0000 * 2^52 * 2 => 1 0000 ---- 0000. * 2
|-- 52 bits --| |-- 52 bits --|
=> 1 . 0000 ---- 0000 * 2^53
|-- 52 bits --|
Sekarang kita mendapatkan 9 007 199 254 740 992 , dan dengan jumlah yang lebih besar dari itu, format apa yang bisa menampung adalah 2 kali dari fraksi , itu berarti sekarang setiap 1 penambahan pada bagian pecahan sebenarnya sama dengan 2 penambahan, itu sebabnya dua kali lipat format 64-bit binary tidak dapat menampung angka ganjil ketika jumlahnya lebih besar dari 9 007 199 254 740 992 :
(consume 2^52 to move radix point to the end)
1 . 0000 ---- 0001 * 2^53 => 1 0000 ---- 0001. * 2
|-- 52 bits --| |-- 52 bits --|
Jadi ketika jumlahnya mencapai lebih dari 9 007 199 254 740 992 * 2 = 18 014 398 509 481 984, hanya 4 kali fraksi yang dapat disimpan:
input: 18014398509481984 + 1 output: 18014398509481984 // expected: 18014398509481985
input: 18014398509481984 + 2 output: 18014398509481984 // expected: 18014398509481986
input: 18014398509481984 + 3 output: 18014398509481984 // expected: 18014398509481987
input: 18014398509481984 + 4 output: 18014398509481988 // expected: 18014398509481988
Bagaimana dengan angka antara [ 2 251 799 813 685 248 , 4 503 599 627 370 496 )?
1 . 0000 ---- 0001 * 2^51 => 1 0000 ---- 000.1
|-- 52 bits --| |-- 52 bits --|
Nilai bit 1 setelah titik radix adalah 2 ^ -1 tepatnya. (= 1/2, = 0,5) Jadi ketika angka kurang dari 4 503 599 627 370 496 (2 ^ 52), ada satu bit yang tersedia untuk mewakili 1/2 kali bilangan bulat :
input: 4503599627370495.5 output: 4503599627370495.5
input: 4503599627370495.75 output: 4503599627370495.5
Kurang dari 2 251 799 813 685 248 (2 ^ 51)
input: 2251799813685246.75 output: 2251799813685246.8 // expected: 2251799813685246.75
input: 2251799813685246.25 output: 2251799813685246.2 // expected: 2251799813685246.25
input: 2251799813685246.5 output: 2251799813685246.5
// If the digits exceed 17, JavaScript round it to print it.
//, but the value is held correctly:
input: 2251799813685246.25.toString(2)
output: "111111111111111111111111111111111111111111111111110.01"
input: 2251799813685246.75.toString(2)
output: "111111111111111111111111111111111111111111111111110.11"
input: 2251799813685246.78.toString(2)
output: "111111111111111111111111111111111111111111111111110.11"
Dan apa kisaran eksponen yang tersedia ? format membagikan 11 bit untuk itu. Format lengkap dari Wiki : (Untuk lebih jelasnya silakan ke sana)
Jadi untuk membuat bagian eksponen menjadi 2 ^ 52, kita harus menetapkan e = 1075.