Số nguyên đầu tiên mà số float của IEEE 754 không có khả năng thể hiện chính xác là gì?


162

Để rõ ràng, nếu tôi đang sử dụng một ngôn ngữ thực hiện IEE 754 nổi và tôi tuyên bố:

float f0 = 0.f;
float f1 = 1.f;

... Và sau đó in chúng ra, tôi sẽ nhận được 0,0000 và 1,0000 - chính xác.

Nhưng IEEE 754 không có khả năng đại diện cho tất cả các số dọc theo đường thẳng thực. Gần bằng không, 'khoảng trống' là nhỏ; khi bạn càng đi xa, khoảng cách càng lớn.

Vì vậy, câu hỏi của tôi là: đối với một số float 754, đây là số nguyên đầu tiên (gần nhất với số 0) không thể được biểu diễn chính xác? Bây giờ tôi chỉ thực sự quan tâm đến số float 32 bit, mặc dù tôi rất muốn nghe câu trả lời cho 64 bit nếu có ai đó đưa ra!

Tôi nghĩ rằng điều này sẽ đơn giản như tính toán 2 bits_of_mantissa và thêm 1, trong đó bits_of_mantissa là bao nhiêu bit mà tiêu chuẩn lộ ra. Tôi đã làm điều này cho các float 32-bit trên máy của mình (MSVC ++, Win64), và nó có vẻ tốt.


Tại sao bạn lại thêm một số nếu bạn muốn một số không thể so sánh được? Và số bạn đã sử dụng hoặc nhận được? Và đây có phải là bài tập về nhà không? Và tiêu đề câu hỏi của bạn nói "số nguyên" nhưng câu hỏi của bạn nói "nổi".
msw

5
Bởi vì tôi đã hình dung rằng tối đa lớp phủ sẽ cho tôi con số đại diện cao nhất. 2 ^ 22. Không, đó là một câu hỏi tò mò. Tôi luôn cảm thấy tội lỗi khi đặt int vào phao, ngay cả khi tôi biết rằng int trong câu hỏi luôn luôn rất nhỏ. Tôi muốn biết giới hạn trên là gì. Theo như tôi có thể nói, tiêu đề và câu hỏi là như nhau, chỉ là cụm từ khác nhau.
Floomi



1
@KyleStrand hoàn nguyên ^ 2. Tôi không biết tại sao một người có vẻ đúng với tôi hơn người kia vào thời điểm đó. Bây giờ cả hai đều có vẻ lúng túng so với
săn lùng

Câu trả lời:


211

2 bit mantissa + 1 + 1

+1 trong số mũ (bit mantissa + 1) là bởi vì, nếu mantissa chứa abcdef...số mà nó đại diện là thực sự 1.abcdef... × 2^e, cung cấp thêm một chút độ chính xác ngầm.

Do đó, số nguyên đầu tiên không thể được biểu diễn chính xác và sẽ được làm tròn là:
For float, 16,777,217 (2 24 + 1).
Cho double, 9,007,199,254,740,993 (2 53 + 1).

>>> 9007199254740993.0
9007199254740992

Tôi đã khai báo a floatvà đặt nó bằng 16.777.217. Nhưng khi tôi in nó bằng cách sử dụng coutnó đã dẫn đến 16.777.216. Tôi đang sử dụng C++. Tại sao tôi không thể nhận được 16.777.217?
natrinitrate

18
@sodiumnitrate Kiểm tra tiêu đề câu hỏi. 16777217 là số nguyên đầu tiên không có khả năng được biểu diễn chính xác.
kennytm

Được rồi cảm ơn. Tôi đã bối rối, xin lỗi về điều đó. Tôi có một câu hỏi khác: sau 16777216, số nguyên tiếp theo có thể biểu thị là 2 * 16777216 không? Khi tôi chạy một chương trình tương tự, tôi nhận được 16777218 bằng cách thêm 2 vào 16777126.
sodiumnitrate

5
Số nguyên tiếp theo thực sự là 16777218, vì 2 giờ trở thành chữ số nhị phân quan trọng cuối cùng.
kennytm

6
Trong C ++, đó là (1 << std::numeric_limits<float>::digits) + 1và trong C , (1 << FLT_MANT_DIG) + 1. Cái trước là tốt vì nó có thể là một phần của mẫu. Không thêm +1 nếu bạn chỉ muốn số nguyên có thể biểu thị lớn nhất.
Henry Schreiner

38

Giá trị lớn nhất được biểu thị bằng số nguyên n bit là 2 n -1. Như đã lưu ý ở trên, a floatcó 24 bit chính xác trong ý nghĩa và dường như ngụ ý rằng 2 24 sẽ không phù hợp.

Tuy nhiên .

Quyền hạn của 2 trong phạm vi của số mũ có thể biểu diễn chính xác là 1.0 × 2 n , do đó, 2 24 có thể phù hợp và do đó, số nguyên không thể biểu thị đầu tiên cho floatlà 2 24 +1. Như đã nói ở trên. Lần nữa.


1
Điều này giải thích rõ ràng phần "chính xác thêm ẩn" của phần khác. Cảm ơn.
chappjc
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.