Float và double có bao nhiêu chữ số có nghĩa trong java?


81

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?


2
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?
Eamon Moloney

@ user1774214 số dấu phẩy động hoàn toàn không được mã hóa giống như số nguyên. hãy xem liên kết tôi đưa ra. Ví dụ, bạn phải hiểu rằng độ chính xác không đồng nhất.
Denys Séguret

@dystroy Tôi không chắc ý của bạn khi nói "độ chính xác không đồng nhất". Nó có độ chính xác khá đồng nhất là 53 và 24 bit, trừ khi bạn đang đề cập đến đơn vị đo lường.
Pascal Cuoq

2
@PascalCuoq có độ chính xác cao hơn cho các số nhỏ hơn. Khi số mũ thay đổi (hoặc điểm nổi) xung quanh, phần định trị tiếp tục biểu diễn cùng một lượng chữ số. Vì vậy, nếu số lớn, phần định trị "không thể đạt tới" các chữ số có nghĩa thấp hơn nhiều, do đó độ chính xác kém hơn.
Vituel

3
@Virtuel Độ chính xác là 53 bit. Đó là những gì chúng tôi gọi là độ chính xác. Có vẻ như bạn đang nghĩ về độ chính xác tuyệt đối hay điều gì đó.
Pascal Cuoq

Câu trả lời:


105

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

http://en.wikipedia.org/wiki/Binary64

http://en.wikipedia.org/wiki/Binary32


ý bạn là gì từ 6 đến 9? nó có thể thay đổi như thế nào? vì vậy nếu tôi chạy một số mã có 8 chữ số thập phân như 0,000000001 nhiều lần, tôi sẽ nhận được các kết quả khác nhau? Đó có phải là ý bạn không?
Aequitas

1
Một số số có thể được biểu diễn chính xác hơn trong hệ nhị phân so với những số khác. Bạn có thể thấy sự khác biệt ở 0,125 (1/8, tám là lũy thừa của hai) và 0,1 (1/10, mười không phải là lũy thừa của hai). Trước đây có nhiều chữ số (thập phân) hơn, nhưng được biểu thị chính xác. Vì vậy, nó có thể là một số có 6 chữ số thập phân có sai số làm tròn lớn hơn một số khác có 8 chữ số.
marcus

9
15,9 chữ số thập phân cho doublevà 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ì.
Marquis of Lorne,

1
Nếu bạn không thích từ trung bình, hãy đề xuất một chỉnh sửa. Nó không phải do tôi thêm vào ngay từ đầu, nó đã được chỉnh sửa bởi người khác ... (và tôi thực sự không thấy cần thiết phải chỉnh sửa đó).
marcus

4
Thật thú vị, thực sự có một chữ số chính xác hơn được lưu trữ trong phần định trị / ý nghĩa. 23 và 52 bit được lưu trữ tương ứng cho float và double, nhưng vì các số được chuẩn hóa nên chúng ta có thể giả sử là 1 bit đứng đầu, sau đó loại bỏ nó. Đây là lý do tại sao độ chính xác hiệu quả tương ứng là 24 và 53 bit. Các phân số thập phân chính xác được tính toán log10 (2 ^ 24) = 7.22 và log10 (2 ^ 53) = 15,95
Georgie

32

Phao 32 bit có độ chính xác khoảng 7 chữ số và số kép 64 bit có độ chính xác khoảng 16 chữ số

Câu trả lời dài:

Số dấu phẩy động có ba thành phần:

  1. Một bit dấu, để xác định xem số đó là số dương hay số âm.
  2. Một số mũ, để xác định độ lớn của một số.
  3. Một phân số, xác định khoảng cách giữa hai giá trị lũy thừa của một số. Điều này đôi khi được gọi là "ý nghĩa và phần định trị, hoặc hệ số"

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ố nbit 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 nlà 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 )


17

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 .


7

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.


3

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 ^ enghĩ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 + 1sản lượng value, vì value + 1không thể được mã hóa sử dụng m * b ^ e, nơi m, beđượ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 nchữ số chính xác như với các số điểm cố định, vì không phải mọi số có nchữ 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 .


2
+1 vì đã đề cập đến "Những điều mọi nhà khoa học máy tính nên biết về số học dấu phẩy động". Tuy nhiên, điều đáng chú ý là mọi số có biểu diễn phân số nhị phân hữu hạn cũng có biểu diễn thập phân hữu hạn. Vấn đề chỉ là chuyển từ thập phân sang nhị phân.
Patricia Shanahan

1

Hãy xem Float.intBitsToFloatDouble.longBitsToDoublegiả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 floattrô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.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.