在以下代码中:
#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
我不明白为什么。这个答案:biggest integer that can be stored in a 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:精确)”
附录
在回复的人和本文Why are doubles added incorrectly in a specific Visual Studio 2008 project?的帮助下,我已经能够找出问题所在。库正在使用_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;
}
此解决方案假设线程混乱浮点精度两次的几率是天文数字小。问题是,我正在使用的值是代表真实世界价值的计时器。所以我不应该冒任何风险。这个问题有灵丹妙药吗?
答案 0 :(得分:0)
从ieee754浮点转换看起来你的double实现实际上是浮点数,当然这是标准所允许的,它要求sizeof double >= sizeof float
。
1510763846的最准确的表示形式是1.510763904E9。