【问题标题】:FPU command FLDL converts double to long double in ST0FPU 命令 FLDL 在 ST0 中将 double 转换为 long double
【发布时间】:2013-03-13 13:26:26
【问题描述】:

我的 C++ 代码中有一个双精度值:

double inch = 25.399999618530273;

在计算中使用时,使用加载到FPU st0寄存器中

fldl -0x90(%ebp)

我可以看到 -0x90(%ebp) 处的 double 值是正确的值。然而,在 FLDL 之后,它在 st0 寄存器中显示为 long double value 25.3999996185302734375,即使我使用 -mpc64 -mfpmath=387 编译并在计算和 fldl 命令之前立即将 FPU 手动设置为双精度:

fpu_control_t cw;
_FPU_GETCW(cw);
cw &= ~_FPU_EXTENDED;
cw |= _FPU_DOUBLE;
_FPU_SETCW(cw);

您能否解释一下,为什么在 _FPU_DOUBLE 模式下 FPU 寄存器仍处于扩展精度模式以及如何解决这个问题?

或者它只是出现为 long double(我在 Eclipse CDT 中查看寄存器),但实际上是在内部没有这些额外数字的情况下运行的?

【问题讨论】:

  • 我不得不承认,我还没有读过《每个程序员都应该知道的浮点运算知识》这本圣经。

标签: c++ linux gcc floating-point


【解决方案1】:

编译程序时,您的数字将转换为 25.3999996185302734375,因为这是最接近 25.399999618530273 的 double 值(使用 IEEE-754 64 位二进制浮点)。将double 转换为long double 没有错误。

当您说您可以看到“-0x90(%ebp) 处的双倍”是正确的值时,如果您没有看到 25.3999996185302734375,那么您没有看到该位置的实际值 - 您正在使用的工具观察值显示不准确。

如果您期望 double 准确地代表 25.399999618530273,那么您会感到失望;它没有,您必须设计您的代码以允许这样做,或者使用 double 以外的其他东西来表示这样的数字。

您使用什么工具测量长度,精度为 0.000000000000001 英寸?那是一把非常精细的尺子,带有非常大的放大镜和机器人增强的眼睛吗?

【讨论】:

  • 25.3999996185302734375 在 Windows VS2010 和 Eclipse CDT 监视窗口中都显示为 25.399999618530273。我有点困惑,他们在这里都显示了不正确的双精度值。 Eclipse 将 25.3999996185302734375L 显示为 25.3999996185302734375 这就是为什么我认为它是 long double 而 25.399999618530273 是 double。
  • @queen3: 25.3999996185302734375 十六进制正好是 0x19.66666;它适合double。十六进制的 25.399999618530273 大约是 0x19.66665FFFFFFFE0798CA9EB295A3085。它不能用double 表示,因为位不合适; double 的有效位只有 53 位。如果某些软件告诉您double 正好包含 25.399999618530273,那么它就是在撒谎。
  • 嗯,那么在 Windows/Linux 调试器中验证真正的 float/double 值的正确方法是什么?
  • @queen3 看看十六进制表示? (如何做到这一点会因调试器而异。)
  • @us2012 好吧,但这不会给我浮动值。无论如何,这是另一个故事和/或问题。
猜你喜欢
  • 1970-01-01
  • 2015-08-23
  • 2021-12-03
  • 2013-01-20
  • 1970-01-01
  • 1970-01-01
  • 2014-02-02
  • 1970-01-01
  • 2019-05-20
相关资源
最近更新 更多