Một float có 32 chữ số nhị phân và một double có 64 chữ số nhị phân? Tài liệu quá khó để hiểu.
Tất cả các bit có dịch sang chữ số có nghĩa không? Hay vị trí của dấu thập phân có chiếm một số bit không?
Một float có 32 chữ số nhị phân và một double có 64 chữ số nhị phân? Tài liệu quá khó để hiểu.
Tất cả các bit có dịch sang chữ số có nghĩa không? Hay vị trí của dấu thập phân có chiếm một số bit không?
Câu trả lời:
float : 32 bit (4 byte) trong đó 23 bit được sử dụng cho phần định trị (khoảng 7 chữ số thập phân). 8 bit được sử dụng cho số mũ, do đó, một float có thể “di chuyển” dấu thập phân sang phải hoặc sang trái bằng cách sử dụng 8 bit đó. Làm như vậy tránh lưu trữ nhiều số 0 trong phần định trị như trong 0,0000003 (3 × 10 -7 ) hoặc 3000000 (3 × 10 7 ). Có 1 bit được dùng làm bit dấu.
double : 64 bit (8 byte) trong đó 52 bit được sử dụng cho phần định trị (khoảng 16 chữ số thập phân). 11 bit được sử dụng cho số mũ và 1 bit là bit dấu.
Vì chúng ta đang sử dụng nhị phân (chỉ 0 và 1), một bit trong phần định trị mặc nhiên là 1 (cả float và double đều sử dụng thủ thuật này) khi số khác không.
Ngoài ra, vì mọi thứ đều ở dạng nhị phân (phần định trị và số mũ) nên các chuyển đổi sang số thập phân thường không chính xác. Các số như 0,5, 0,25, 0,75, 0,125 được lưu trữ chính xác, nhưng 0,1 thì không. Như những người khác đã nói, nếu bạn cần lưu trữ xu một cách chính xác, không sử dụng float hoặc double, hãy sử dụng int, long, BigInteger hoặc BigDecimal.
Nguồn:
http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers
double
và 7,2 cho float
, nghĩa là 15 và 7. Một số số lớn hơn có thể được biểu diễn trong mỗi trường hợp và không có chữ số nào áp dụng cho phân số, nhưng không có 'trung bình' về nó và không có nguồn nào của bạn cho biết nếu không thì.
Câu trả lời dài:
Số dấu phẩy động có ba thành phần:
Về cơ bản, điều này hoạt động với sign * 2^exponent * (1 + fraction)
. “Kích thước” của số, nó là số mũ, không liên quan đến chúng ta, vì nó chỉ chia tỷ lệ giá trị của phần phân số. Biết rằng log₁₀(n)
với số chữ số của n
, † chúng ta có thể xác định độ chính xác của một số dấu phẩy động với log₁₀(largest_possible_fraction)
. Bởi vì mỗi bit trong float lưu trữ 2 khả năng, một số n
bit nhị phân có thể lưu trữ một số lên đến 2ⁿ - 1
(tổng các 2ⁿ
giá trị trong đó một trong các giá trị bằng 0). Điều này hơi khó hiểu một chút, bởi vì hóa ra số dấu phẩy động được lưu trữ với một bit nhỏ hơn chúng có thể sử dụng, bởi vì số 0 được biểu diễn đặc biệt và tất cả các số khác 0 đều có ít nhất một bit nhị phân khác không. ‡
Kết hợp này, các chữ số chính xác đối với một số dấu chấm động được
log₁₀(2ⁿ)
, nơi n
là số bit của phần số điểm của nổi. Một phao 32 bit có 24 bit phân số cho độ chính xác ≈7,22 chữ số thập phân và một số kép 64 bit có 53 bit phân số cho độ chính xác ≈15,95 chữ số thập phân.
Để biết thêm về độ chính xác của dấu chấm động, bạn có thể muốn đọc về khái niệm epsilon máy .
† Đối với n ≥ 1
ít nhất - đối với các số khác, công thức của bạn sẽ giống hơn
⌊log₁₀(|n|)⌋ + 1
.
‡ “Quy tắc này còn được gọi là quy ước bit dẫn đầu, quy ước bit ngầm, hoặc quy ước bit ẩn.” ( Wikipedia )
Từ đặc tả java :
Các loại dấu phẩy động là float và double, được liên kết về mặt khái niệm với các giá trị và phép toán IEEE 754 định dạng 64 bit độ chính xác đơn và độ chính xác kép như được chỉ định trong IEEE Standard for Binary Floating-Point Arithmetic, ANSI / IEEE Tiêu chuẩn 754-1985 (IEEE, New York).
Vì thật khó để làm bất cứ điều gì với các con số mà không hiểu những điều cơ bản về IEEE754, đây là một liên kết khác .
Điều quan trọng là phải hiểu rằng độ chính xác không đồng nhất và đây không phải là nơi lưu trữ chính xác các số như được thực hiện đối với số nguyên.
Một ví dụ :
double a = 0.3 - 0.1;
System.out.println(a);
bản in
0.19999999999999998
Nếu bạn cần độ chính xác tùy ý (ví dụ cho mục đích tài chính), bạn có thể cần Số thập phân lớn .
Một câu trả lời toán học bình thường.
Hiểu rằng một số dấu phẩy động được thực hiện dưới dạng một số bit đại diện cho số mũ và phần còn lại, hầu hết cho các chữ số (trong hệ nhị phân), một trong những tình huống sau:
Với số mũ cao, giả sử là 10²³ nếu bit ít quan trọng nhất bị thay đổi, sẽ xuất hiện sự khác biệt lớn giữa hai số có thể tách rời liền kề. Hơn nữa, dấu thập phân cơ số 2 làm cho nhiều số cơ số 10 chỉ có thể gần đúng; 1/5, 1/10 là số vô tận.
Vì vậy, nói chung : không nên sử dụng số dấu phẩy động nếu bạn quan tâm đến các chữ số có nghĩa. Đối với số tiền có phép tính, e, a, tốt nhất nên sử dụng BigDecimal .
Đối với vật lý, dấu phẩy động nhân đôi là đủ, số liệu nổi gần như không bao giờ. Hơn nữa, phần dấu phẩy động của bộ xử lý, FPU, thậm chí có thể sử dụng nội bộ nhiều hơn một chút.
Các số dấu phẩy động được mã hóa bằng cách sử dụng một dạng số mũ, có m * b ^ e
nghĩa là không giống số nguyên. Câu hỏi bạn hỏi sẽ có ý nghĩa trong bối cảnh số điểm cố định . Có rất nhiều thư viện số học điểm cố định có sẵn.
Về số học dấu phẩy động: Số chữ số thập phân phụ thuộc vào cách trình bày và hệ thống số. Ví dụ, có những số tuần hoàn ( 0.33333
) không có dạng trình bày hữu hạn ở dạng thập phân nhưng có dạng ở dạng nhị phân và ngược lại.
Ngoài ra nó là đáng nói đến là các số dấu phảy lên đến một điểm nào đó làm có một sự khác biệt lớn hơn một, nghĩa là value + 1
sản lượng value
, vì value + 1
không thể được mã hóa sử dụng m * b ^ e
, nơi m
, b
và e
được cố định chiều dài. Điều tương tự cũng xảy ra đối với các giá trị nhỏ hơn 1, tức là tất cả các điểm mã có thể có không có cùng khoảng cách.
Vì điều này không có độ chính xác của các n
chữ số chính xác như với các số điểm cố định, vì không phải mọi số có n
chữ số thập phân đều có mã hóa IEEE.
Có một tài liệu gần như bắt buộc mà bạn nên đọc sau đó giải thích về số dấu phẩy động: Điều mà mọi nhà khoa học máy tính nên biết về số học dấu phẩy động .
Hãy xem Float.intBitsToFloat
và Double.longBitsToDouble
giải thích cách các bit tương ứng với số dấu phẩy động. Đặc biệt, các bit bình thường float
trông giống như
s * 2^exp * 1.ABCDEFGHIJKLMNOPQRSTUVW
trong đó A ... W là 23 bit - 0s và 1s - đại diện cho một phân số trong hệ nhị phân - s là +/- 1, được biểu diễn bằng 0 hoặc 1 tương ứng và exp là một số nguyên 8 bit có dấu.