Nhiều câu trả lời từ thời gian trước đã cho thấy kết quả true
của 9007199254740992 === 9007199254740992 + 1
việc xác minh rằng 9 007 199 254 740 991 là số nguyên tối đa và an toàn.
Điều gì xảy ra nếu chúng ta tiếp tục tích lũy:
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
Chúng ta có thể tìm ra rằng trong số các số lớn hơn 9 007 199 254 740 992 , chỉ các số chẵn là có thể biểu diễn .
Đây là một lối vào để giải thích cách thức định dạng nhị phân 64 bit chính xác kép hoạt động trên này. Hãy xem 9 007 199 254 740 992 được tổ chức (đại diện) bằng cách sử dụng định dạng nhị phân này.
Sử dụng một phiên bản ngắn gọn để trình diễn nó từ 4 503 599 627 370 496 :
1 . 0000 ---- 0000 * 2^52 => 1 0000 ---- 0000.
|-- 52 bits --| |exponent part| |-- 52 bits --|
Ở bên trái của mũi tên, chúng ta có giá trị bit 1 và một điểm cơ số liền kề , sau đó bằng cách nhân 2^52
, chúng ta phải di chuyển điểm cơ số 52 bước và đi đến cuối. Bây giờ chúng tôi nhận được 4503599627370496 trong nhị phân.
Bây giờ chúng ta bắt đầu tích lũy 1 đến giá trị này cho đến khi tất cả các bit được đặt thành 1, bằng 9 007 199 254 740 991 theo số thập phân.
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.
Bây giờ, vì ở định dạng nhị phân 64 bit có độ chính xác kép , nó hoàn toàn phân bổ 52 bit cho phân số, không còn bit nào để mang thêm 1, vì vậy, điều chúng ta có thể làm là đặt tất cả các bit về 0 và Thao tác phần số mũ:
|--> 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 --|
Bây giờ chúng ta nhận được 9 007 199 254 740 992 và với số lượng lớn hơn nó, định dạng có thể giữ bằng 2 lần phân số , có nghĩa là bây giờ cứ 1 phần bổ sung trên phần phân số thực sự bằng 2 phần bổ sung, đó là lý do tại sao tăng gấp đôi -định dạng định dạng nhị phân 64 bit không thể giữ các số lẻ khi số lớn hơn 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 --|
Vì vậy, khi số lượng lớn hơn 9 007 199 254 740 992 * 2 = 18 014 398 509 481 984, chỉ có thể giữ 4 lần phân số :
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
Làm thế nào về số giữa [ 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 --|
Giá trị bit 1 sau điểm cơ số chính xác là 2 ^ -1. (= 1/2, = 0,5) Vì vậy, khi số nhỏ hơn 4 503 599 627 370 496 (2 ^ 52), có một bit có sẵn để biểu thị 1/2 lần của số nguyên :
input: 4503599627370495.5 output: 4503599627370495.5
input: 4503599627370495.75 output: 4503599627370495.5
Ít hơn 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"
Và phạm vi có sẵn của phần số mũ là gì? định dạng phân bổ 11 bit cho nó. Định dạng hoàn chỉnh từ Wiki : (Để biết thêm chi tiết xin vui lòng đến đó)
Vì vậy, để làm cho phần số mũ là 2 ^ 52, chúng ta chính xác cần đặt e = 1075.