[英]Unexpected result after converting uint64_t to double
在以下代碼中:
#include <iostream>
...
uint64_t t1 = 1510763846;
uint64_t t2 = 1510763847;
double d1 = (double)t1;
double d2 = (double)t2;
// d1 == t2 => evaluates to true somehow?
// t1 == d2 => evaluates to true somehow?
// d1 == d2 => evaluates to true somehow?
// t1 == t2 => evaluates to false, of course.
std::cout << std::fixed <<
"uint64_t: " << t1 << ", " << t2 << ", " <<
"double: " << d1 << ", " << d2 << ", " << (d2+1) << std::endl;
我得到這個輸出:
uint64_t: 1510763846, 1510763847, double: 1510763904.000000, 1510763904.000000, 1510763905.000000
我不明白為什么。 這個答案: 可以存儲在double中的最大整數表示最多2 ^ 53(9007199254740992)的整數可以存儲在一個double
精度而不會丟失精度。
當我開始用雙打計算時,我實際上會出錯,所以這不僅僅是打印問題。 (例如1510763846和1510763847均給出1510763904)
雙倍可以添加到然后出來正確也是非常奇怪的(d2 + 1 == 1510763905.000000)
基本原理:我將這些數字轉換為雙數,因為我需要在Lua中使用它們,它只支持浮點數。 我確定我正在使用double
作為lua_Number
類型編譯Lua lib,而不是float
。
std::cout << sizeof(t1) << ", " << sizeof(d2) << std::endl;
輸出
8, 8
我正在使用VS 2012與目標MachineX86,工具包v110_xp。 浮點模型“精確(/ fp:精確)”
附錄
在回復的人和本文的幫助下, 為什么在特定的Visual Studio 2008項目中錯誤地添加了雙打? ,我已經能夠找出問題所在。 庫正在使用_set_controlfp,_control87,_controlfp或__control87_2等函數將可執行文件的精度更改為“single”。 這就是為什么uint64_t轉換為double的行為就好像它是一個浮點數。
在執行文件搜索上述函數名稱和“MCW_PC”(用於精確控制)時,我發現可能設置了以下庫:
現在我想重新解釋一下我的問題:
如何確保每次都能正確地從uint64_t
轉換為double
,而不是:
天真的代碼將是這樣的:
double toDouble(uint64_t i)
{
double d;
do {
_fpreset();
d = i;
_fpreset();
} while (d != i);
return d;
}
double toDouble(int64_t i)
{
double d;
do {
_fpreset();
d = i;
_fpreset();
} while (d != i);
return d;
}
這個解決方案假設一個線程搞亂浮點精度兩次的幾率是天文數字小。 問題是,我正在使用的值是代表真實世界價值的計時器。 所以我不應該冒任何風險。 這個問題有靈丹妙葯嗎?
從ieee754浮點轉換看起來你的double實現實際上是浮點數,當然這是標准所允許的,它規定了sizeof double >= sizeof float
。
最准確的1510763846表示是1.510763904E9。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.