2017-01-04 21 views
7

Trong một nỗ lực để xác minh (sử dụng VS2012) tuyên bố (câu 2) của một cuốn sách màchuyển đổi ngầm từ lâu lâu nổi lãi suất bất ngờ kết quả

When we assign an integral value to an object of floating-point type, the fractional part is zero. 
Precision may be lost if the integer has more bits than the floating-point object can accommodate. 

tôi viết prog wee sau:

#include <iostream> 
#include <iomanip> 

using std::cout; 
using std::setprecision; 

int main() 
{ 
    long long i = 4611686018427387905; // 2^62 + 2^0 

    float f = i; 

    std::streamsize prec = cout.precision(); 

    cout << i << " " << setprecision(20) << f << setprecision(prec) << std::endl; 

    return 0; 
} 

Đầu ra là

4611686018427387905 4611686018427387900 

tôi mong đợi đầu ra có dạng

4611686018427387905 4611690000000000000 

Làm cách nào một phao 4 byte có thể giữ lại quá nhiều thông tin về số nguyên 8 byte? Có giá trị nào cho tôi thực sự thể hiện khiếu nại không?

Trả lời

5

Nổi không lưu trữ dữ liệu của chúng trong cơ sở 10, chúng lưu trữ trong cơ sở 2. Do đó, 4611690000000000000 không thực sự là một số rất tròn. Biểu thị nhị phân của nó là:

100000000000000000000111001111100001000001110001010000000000000. 

Như bạn có thể thấy, sẽ mất rất nhiều dữ liệu để ghi chính xác. Số điện thoại mà thực sự in, tuy nhiên, có các đại diện sau nhị phân:

11111111111111111111111111111111111111111111111111111111111100 

Như bạn có thể thấy, đó là một số tròn nhiều, và thực tế là nó tắt bằng 4 từ một sức mạnh của hai là khả năng do làm tròn trong thuật toán convert-to-base-10.

Như một ví dụ về một con số đó sẽ không phù hợp trong một phao đúng cách, hãy thử số bạn mong đợi:

4611690000000000000 

Bạn sẽ nhận thấy rằng đó sẽ đi ra rất khác nhau.

4

Các phao giữ lại rất nhiều thông tin vì bạn đang làm việc với một số đó là rất gần gũi với một sức mạnh của 2.

Những con số định dạng phao cửa hàng trong ký hiệu khoa học cơ bản nhị phân. Trong trường hợp của bạn, nó được lưu trữ như một cái gì đó như

1.0000000 ... [61 zeroes] ... 00000001 * 2^62.

Định dạng nổi không thể lưu trữ 62 vị trí thập phân, vì vậy cuối cùng 1 bị cắt bỏ ... nhưng chúng tôi còn lại với 2^62, gần như chính xác bằng số bạn đang cố gắng lưu trữ.

Tôi rất xấu trong các ví dụ sản xuất, nhưng CERT thì không; bạn có thể xem ví dụ về những gì xảy ra với các chuyển đổi số bungled here. Lưu ý rằng ví dụ này là trong Java, nhưng C++ sử dụng các kiểu dấu phẩy động tương tự; ngoài ra, ví dụ đầu tiên là chuyển đổi giữa 4 byte int và 4 byte float 4 byte, nhưng điều này chứng tỏ quan điểm của bạn hơn (có ít thông tin số nguyên cần được lưu trữ hơn trong ví dụ của bạn nhưng vẫn không thành công).

Các vấn đề liên quan