[英]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.