Giới hạn độ chính xác trên double
buộc đại diện nhị phân làm tròn thành công suất gần nhất là 2
, tăng số mũ trong biểu diễn dấu phẩy động của giá trị double
. Điều này xảy ra bởi vì một phần tử của double, bao gồm bit 1
ngụ ý, là 53 bit, nhưng một bit là long
có 64 bit.
Section 5.1.2 of the JLS bao gồm những gì có thể xảy ra trong này chuyển đổi nguyên thủy mở rộng:
Chuyển đổi nguyên thủy ngày càng lớn từ int nổi, hoặc từ lâu nổi, hoặc từ lâu để tăng gấp đôi, có thể dẫn đến việc mất độ chính xác - đó là, kết quả có thể mất một số bit quan trọng nhất của giá trị. Trong trường hợp này, giá trị dấu chấm động kết quả sẽ là phiên bản được làm tròn chính xác của giá trị số nguyên, sử dụng chế độ vòng tròn gần nhất của IEEE 754 (§4.2.4).
(tôi nhấn mạnh)
Ở đây, tôi sử dụng Double.doubleToLongBits
để bảo tồn các bit của một double
trong một long
, và Long.toHexString
để in ra các giá trị hex của bản gốc double
s.
System.out.format("Max(%s): %-5d Min(%s): %-5d -1(%s): %-5d%n",
Long.toHexString(Double.doubleToLongBits(dmax)), Math.getExponent(dmax),
Long.toHexString(Double.doubleToLongBits(dmax)), Math.getExponent(dmin),
Long.toHexString(Double.doubleToLongBits(dneg)), Math.getExponent(dneg));
Output:
Max(43e0000000000000): 63 Min(43e0000000000000): 63 -1(bff0000000000000): 0
Max(43d0000000000000): 62 Min(43d0000000000000): 62 -1(43e0000000000000): 63
Max(43c0000000000000): 61 Min(43c0000000000000): 61 -1(43d0000000000000): 62
Max(43b0000000000000): 60 Min(43b0000000000000): 60 -1(43c0000000000000): 61
Max(43a0000000000000): 59 Min(43a0000000000000): 59 -1(43b0000000000000): 60
Max(4390000000000000): 58 Min(4390000000000000): 58 -1(43a0000000000000): 59
Max(4380000000000000): 57 Min(4380000000000000): 57 -1(4390000000000000): 58
Max(4370000000000000): 56 Min(4370000000000000): 56 -1(4380000000000000): 57
Max(4360000000000000): 55 Min(4360000000000000): 55 -1(4370000000000000): 56
Max(4350000000000000): 54 Min(4350000000000000): 54 -1(4360000000000000): 55
Max(433fffffffffffff): 52 Min(433fffffffffffff): 53 -1(4350000000000000): 54
Max(432ffffffffffffe): 51 Min(432ffffffffffffe): 52 -1(433fffffffffffff): 52
Các long
giá trị ban đầu với hơn 53 1
bit được làm tròn lên khi chuyển đổi sang một double
, mất độ chính xác. Trường số mũ bao gồm các bit 2
đến 12
, hiển thị trong 3 số hex đầu tiên được in ở trên.
Khi giá trị được dịch chuyển dưới mức 53 1
bit, độ chính xác của double
hiện đủ để giữ giá trị mà không làm tròn (vòng tròn không còn cần thiết) và bit của mantissa được hiển thị dưới dạng chữ số thập phân 'f'.Có sự gián đoạn trong trường số mũ, chuyển từ 435
sang 433
, giải thích lý do tại sao có gián đoạn do kết quả của Math.getExponent
, từ 54
đến 52
.
Điều này có ý nghĩa hoàn hảo. Sau khi đọc bài viết của bạn, tôi buộc các giá trị lớn hơn 2^53 - 1 để giảm 11 bit quan trọng nhất của chúng bằng: 'value & = 0xFFFFFFFFFFFFF700L;' trước khi chuyển đổi thành một đôi, làm cho làm tròn không cần thiết. Tôi cũng quên phần định nghĩa có chút hàm ý. Cảm ơn các câu trả lời chi tiết! –