簡體   English   中英

從long long到float的隱式轉換會產生意外結果

[英]Implicit conversion from long long to float yields unexpected result

試圖驗證(使用VS2012)一本書的索賠(第二句)

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.

我寫了以下的編程:

#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;
}

輸出是

4611686018427387905 4611686018427387900

我期待表格的輸出

4611686018427387905 4611690000000000000

4字節的浮點數如何能夠保留8字節整數的大量信息? 是否有實際證明索賠的i值?

浮點數不會將數據存儲在基數10中,而是將它存儲在基數2中。因此, 4611690000000000000實際上不是一個非常圓的數字。 它的二進制表示是:

100000000000000000000111001111100001000001110001010000000000000. 

如您所見,這需要大量數據才能精確記錄。 但是,實際打印的數字具有以下二進制表示形式:

11111111111111111111111111111111111111111111111111111111111100

正如你所看到的那樣,這是一個更加圓整的數字,並且它的功率為2,這可能是由於轉換為base-10算法的四舍五入。

作為一個適合浮動的數字的例子,嘗試你期望的數字:

4611690000000000000

你會注意到這種情況會有很大不同。

浮點數保留了很多信息,因為你使用的數字非常接近2的冪。

浮點格式以基本二進制科學記數法存儲數字。 在你的情況下,它被存儲為類似的東西

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

浮動格式不能存儲62個小數位,所以最后1個被截斷...但是我們留下了2 ^ 62,這幾乎完全等於你想要存儲的數字。

我不擅長制造示例,但CERT不是; 您可以在此處查看有關錯誤的號碼轉換的示例。 請注意,該示例使用的是Java,但C ++使用相同的浮點類型; 另外,第一個例子是4字節int和4字節float之間的轉換,但這進一步證明了你的觀點(需要存儲的整數信息少於你的例子中的整數信息,但它仍然失敗)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM