gpt4 book ai didi

c++ - 将 uint64_t 转换为 double 后出现意外结果

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:50:09 30 4
gpt4 key购买 nike

在下面的代码中:

#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 中而不会丢失精度。

当我开始用 double 进行计算时,我实际上遇到了错误,所以这不仅仅是打印问题。 (例如 1510763846 和 1510763847 都给出 1510763904)

同样很奇怪的是,double 可以直接相加然后正确输出 (d2+1 == 1510763905.000000)

基本原理:我将这些数字转换为 double ,因为我需要在 Lua 中使用它们,它只支持 float 。我确定我正在使用 double 作为 lua_Number 类型编译 Lua 库,而不是 float

std::cout << sizeof(t1) << ", " << sizeof(d2) << std::endl;

输出

8, 8

我正在使用 VS 2012 和目标 MachineX86,工具包 v110_xp。浮点模型“精确 (/fp:precise)”

附录

在回复的人和这篇文章的帮助下Why are doubles added incorrectly in a specific Visual Studio 2008 project? ,我已经能够查明问题所在。库正在使用 _set_controlfp、_control87、_controlfp 或 __control87_2 之类的函数将我的可执行文件的精度更改为“单一”。这就是为什么 uint64_t 转换为 double 的行为就像它是 float 一样。

在对上述函数名称和用于 Precision Control 的“MCW_PC”进行文件搜索时,我发现以下库可能已经设置了它:

  • 安卓NDK
  • 提升::数学
  • 提升::数字
  • DirectX(我们使用的是 2010 年 6 月版)
  • FMod(非 EX)
  • Pyro 粒子引擎

现在我想重新表述一下我的问题:

如何确保从 uint64_tdouble 的转换每次都能正确进行,而无需:

  1. 每次可能的转换发生时都必须调用 _fpreset()(考虑函数参数)
  2. 不得不担心库的线程会改变我的 _fpreset() 和转换之间的浮点精度?

朴素的代码应该是这样的:

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

此解决方案假设线程干扰浮点精度 两次 的几率在天文数字上很小。问题是,我正在使用的值是代表真实世界值的计时器。所以我不应该冒险。这个问题有 Elixir 吗?

最佳答案

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

The most accurate representation of 1510763846 is 1.510763904E9.

关于c++ - 将 uint64_t 转换为 double 后出现意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47312877/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com