【问题标题】:Extended precision floating point dangers in C# [duplicate]C#中的扩展精度浮点危险[重复]
【发布时间】:2015-11-13 12:50:53
【问题描述】:

我正在根据我正在阅读的一篇论文编写一个多精度算术库。能够保证我使用的浮点数的属性非常重要。特别是,它们遵守双精度浮点数的 IEEE 754 标准。显然,我不能保证我的代码在意外平台上的行为,但是对于我正在编写的 x86 和 x64 芯片组,我担心一个特殊的危险。显然,部分或全部 x86 / x64 芯片组可能会在其 FPU 寄存器中使用扩展精度浮点数,精度为 80 位。我不能容忍在扩展精度 FPU 中处理我的算术而不在每次操作后四舍五入到双精度,因为我正在使用的算法的正确性证明依赖于四舍五入的发生。我可以很容易地识别出扩展精度可能会破坏这些算法的情况。

我正在用 C# 编写我的代码。如何保证某些值是四舍五入的?在 C 语言中,我将变量声明为 volatile,强制将它们写回 RAM。这很慢,我宁愿将寄存器中的数字保留为 64 位浮点数,但这些算法的正确性是重点,而不是速度。无论如何,我需要 C# 的解决方案。如果这看起来不可行,我会用不同的语言来解决这个问题。

【问题讨论】:

  • 作为缺少volatile double 的解决方法,您可以在每次操作后将操作数转换为字节或从字节转换......这真的很sloooooowwww ..

标签: c# floating-point-precision floating-point-conversion


【解决方案1】:

C# 规范对此主题有这样的说法:

只有以过高的性能成本才能使此类硬件体系结构以较低的精度执行浮点运算,而不是要求实现同时丧失性能和精度,C# 允许将更高精度的类型用于所有浮点运算点操作。除了提供更精确的结果之外,这很少有任何可衡量的影响。

因此,需要第三方库来模拟符合 IEEE 754 的 FPU 的行为。其中一个是 SoftFloat,它创建了一个类型 SoftFloat,它使用运算符重载来模拟标准的 double 行为。

【讨论】:

  • 这很可能是我的答案,尽管我会给它更多时间让其他人参与进来。
【解决方案2】:

80 位中间值的一个明显问题是编译器和优化器决定何时将值截断回 64 位。因此,不同的编译器最终可能会为相同的浮点运算序列产生不同的结果。一个例子是像 abcd 这样的操作。根据 80 位浮点寄存器的可用性,编译器可能会将 ab 舍入为 64 位,并将 c*d 保留为 80 位。我想这是您需要消除这种不确定性的问题的根源。

我认为您在托管代码中的选择非常有限。您可以像建议的其他答案一样使用第 3 方软件仿真。或者,也许您可​​以尝试将双打强制为长并返回。我无法检查这是否真的有效,但你可以在操作之间尝试这样的事情:

public static double Truncate64(double val)
{
    unsafe
    {
        long l = *((long*) &val);
        return *((double*) &l);
    }
}

这也是类型检查:

public static double Truncate64(double val)
{
    unsafe
    {
        return *((long*) &val);
    }
}

希望对您有所帮助。

【讨论】:

  • 优化器是否有理由不消除这些强制转换?
猜你喜欢
  • 2012-04-26
  • 2021-09-16
  • 2011-02-23
  • 2012-11-08
  • 2015-05-01
  • 2016-02-17
  • 1970-01-01
相关资源
最近更新 更多