【问题标题】:Will different math CPUs yield the same floating point results?不同的数学 CPU 会产生相同的浮点结果吗?
【发布时间】:2014-07-20 23:47:56
【问题描述】:

我正在开发具有必须在 Linux、UNIX 和 Windows 上运行的单元测试的操作系统可移植软件。

想象一下这个断言 IEEE 单精度浮点值 1.26743237e+015f 被转换为字符串的单元测试:

void DataTypeConvertion_Test::TestToFloatWide()
{
    CDataTypeConversion<wchar_t> dataTypeConvertion;
    float val = 1.26743237e+015f;
    wchar_t *valStr = (wchar_t*)dataTypeConvertion.ToFloat(val);
    std::wcout << valStr << std::endl;
    int result = wcscmp(L"1.26743E+015", valStr);
    CPPUNIT_ASSERT_EQUAL(0, result);
    delete [] valStr;
}

我的问题是:all 操作系统和处理器会将浮点数转换为字符串“1.26743E+015”,只要浮点数是 IEEE 吗?我在问,因为我知道数学 CPU 可能不会返回准确的结果,我想知道这是否会在不同的处理器上产生不同的结果,因为它们可能在处理器架构内部具有不同的 IEEE 浮点运算硬件实现。

【问题讨论】:

  • 可以通过std::numeric_limits::epsilon&lt;float&gt;()获取当前平台实际支持的float精度。对于不同的机器架构/FPU,它可能会有所不同。
  • 浮点计算在同一台机器上会产生不一致的结果,没有理由假设它在不同的操作系统上会变得更好。 sn-p 方式太人为且不完整,无法猜测。显然,您已经通过尝试在 float 中存储比它能够存储的更多数字来引发麻烦。非常不清楚截断是如何进行的。它会起作用,编译器的优化器和浮点处理器的舍入模式用这个特定值搞砸结果的可能性很小。
  • 对于 X86,内部浮点计算可以以 32 位、64 位或 80 位格式执行,具体取决于浮点控制字的设置,而浮点控制字的设置可能因编译器而异。
  • @LưuVĩnhPhúc 如果您只是使用非过时的 Java 标准而没有进一步明确表示您需要可重现的浮点,那么您将无法获得可重现的浮点。 .NET 更糟糕:基本上没有办法指定您想要可重现的浮点数。并且大多数其他虚拟机都是用 C 实现的,并且让它们的用户受制于 C 的浮点变幻莫测。请在回答中解释您的意思或撤回您的评论。

标签: c++ floating-point precision floating-accuracy floating-point-conversion


【解决方案1】:

遗憾的是,答案很可能是否定的。不保证跨平台的浮点数与任意字符串之间的转换。

至少在原则上,您可能遇到的所有处理器都符合 IEEE 754 标准。该标准相当严格,以至于它定义了浮点运算。您可以对浮点数进行加法/减法/乘法运算或除法运算,合理期望在位级别跨平台获得相同的结果。

该标准还定义了与“字符表示”的转换。原则上,要求兼容的实现是兼容的,但它有“回旋余地”。并非所有数字都必须产生相同的结果。

您还应该注意,默认精度和格式可能因平台而异。

话虽如此,只要 (a) 您控制字符串的宽度和精度,而不是将其保留为默认值 (b) 您选择的精度在最大值范围内,您就可以实现您想要的结果可用于特定格式 (c) 避免 NaN 和类似的。

here的文章很有帮助。

【讨论】:

  • 将字符串转换为double 的.NET 方法并非在所有情况下都执行正确的舍入;对于某些输入字符串,当使用 x87 浮点数学时,它们将在 32 位模式下正确舍入,但在使用 SSE 浮点数学的 64 位模式下则不会。所有平台都应该精确地转换在精确表示值的 1/4ulp 范围内的每个字符串,但是当给定一个与最近的可表示值相差近 1/2ulp 的字符串时可能会有所不同(没有任何东西可以超过 1/2ulp最接近的可表示值,因为其他一些可表示的值会更接近它)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多