将uint64_t转换为double

时间:2017-11-15 16:43:06

标签: c++ precision uint64

在以下代码中:

#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”时,我发现了以下可能设置它的库:

  • Android NDK
  • 升压::数学
  • 升压::数字
  • DirectX(我们正在使用2010年6月)
  • FMod(非EX)
  • Pyro粒子引擎

现在我想重新解释一下我的问题:

如何确保每次都能正确转换uint64_tdouble,而不会:

  1. 每次发生可能的转换时都要调用_fpreset()(想想函数参数)
  2. 不得不担心库的线程会改变我的_fpreset()和转换之间的浮点精度吗?
  3. 天真的代码就是这样的:

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

    此解决方案假设线程混乱浮点精度两次的几率是天文数字小。问题是,我正在使用的值是代表真实世界价值的计时器。所以我不应该冒任何风险。这个问题有灵丹妙药吗?

1 个答案:

答案 0 :(得分:0)

从ieee754浮点转换看起来你的double实现实际上是浮点数,当然这是标准所允许的,它要求sizeof double >= sizeof float

  
    

1510763846的最准确的表示形式是1.510763904E9。