Багато відповідей від раніше показали результат true
від 9007199254740992 === 9007199254740992 + 1
перевірити , що 9 007 199 254 740 991 максимальне і безпечне ціле.
Що робити, якщо ми продовжуємо робити накопичення:
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
Ми могли б дізнатися, що серед чисел більше 9 007 199 254 740 992 , тільки парне число представимо .
Це вхід, щоб пояснити, як 64-розрядний бінарний формат подвійної точності на це працює. Давайте подивимось, як 9 007 199 254 740 992 провести (представлено) за допомогою цього бінарного формату.
Використовуючи коротку версію, щоб продемонструвати її з 4 503 599 627 370 496 :
1 . 0000 ---- 0000 * 2^52 => 1 0000 ---- 0000.
|-- 52 bits --| |exponent part| |-- 52 bits --|
У лівій частині стрілки маємо бітове значення 1 і сусідню точку радіації , множимо 2^52
ми праворуч переміщуємо радіаційну точку на 52 кроки, і вона йде до кінця. Тепер ми отримуємо 4503599627370496 у двійковій формі.
Тепер ми починаємо накопичувати 1 до цього значення, поки всі біти не будуть встановлені в 1, що дорівнює 9 007 199 254 740 991 у десятковій частині.
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.
Тепер, оскільки в 64-бітовому бінарному форматі з подвоєною точністю він суворо виділяє 52 біти на дріб, більше біт не доступний для додавання ще одного 1, тому ми можемо зробити, щоб усі біти повернути до 0, і маніпулювати експонентною частиною:
|--> 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 --|
Тепер ми отримуємо 9 007 199 254 740 992 , і число, яке перевищує його, може містити формат у 2 рази долі , це означає, що кожне 1 додавання на частину дробу фактично дорівнює 2 доданню, тому подвійне точність 64-бітного двійкового формату не може містити непарних чисел, коли число більше 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 --|
Отже, коли число досягне більше 9 007 199 254 740 992 * 2 = 18 014 398 509 481 984, лише 4 рази частка може бути утримана:
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
Як щодо числа між [ 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 --|
Значення біта 1 після точки радіації дорівнює 2 ^ -1 точно. (= 1/2, = 0,5) Отже, коли число менше 4 503 599 627 370 496 (2 ^ 52), є один біт, який представляє 1/2 рази цілого числа :
input: 4503599627370495.5 output: 4503599627370495.5
input: 4503599627370495.75 output: 4503599627370495.5
Менше 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"
І який доступний діапазон експонентної частини ? формат виділяє для нього 11 біт. Повний формат від Wiki : (Детальніше просимо туди)
Отже, щоб скласти частину експонента 2 ^ 52, нам точно потрібно встановити e = 1075.