【问题标题】:what languages expose IEEE 754 traps to the developer?哪些语言向开发人员公开了 IEEE 754 陷阱?
【发布时间】:2010-10-16 11:48:26
【问题描述】:

出于教育目的,我想玩这些陷阱。

数值演算中默认行为的一个常见问题是我们“错过”了出现在错误运算中的 Nan(或 +-inf)。默认行为是通过计算进行传播,但一些操作(如比较)会破坏链并松开 Nan,其余处理继续进行,而不承认算法前面步骤中的奇异性。

有时我们有办法对此类事件做出反应:延长函数(“在我的情况下为 0/0 = 12”),或在时域模拟中放弃步骤并尝试使用其他设置(如预测器,步长或其他)。

所以这是我的问题:您知道将 IEEE754 陷阱暴露给开发人员的语言吗?我不想为此和 ASM 搞混。

【问题讨论】:

    标签: floating-point ieee-754 floating-point-exceptions


    【解决方案1】:

    据我所知,在 C 和 C++ 中处理浮点异常有两种选择:

    首先,如果您禁用/屏蔽浮点异常(大多数环境默认这样做),您可以通过调用fetestexcept 来查看是否发生了任何浮点异常。 fetestexcept 在 Visual C++ 中不可用,但您可以很容易地窃取 MinGW 运行时的实现。 (它在公共领域。)一旦标记了异常,在调用 feclearexcept 之前它不会被清除,因此您可以在一系列计算结束时调用 fetestexcept 以查看其中是否有任何引发异常。这不会为您提供您要求的陷阱,但它确实可以让您测试是否发生了诸如 NaN 或 +/-inf 之类的问题并根据需要做出反应。

    其次,您可以通过在 Linux 中调用 feenableexcept 或在 Windows 中调用 _controlfp 来启用/取消屏蔽浮点异常。操作系统如何处理处理器生成的浮点异常取决于您的操作系统。

    • 在 Linux 中,操作系统会发送一个 SIGFPE 信号,因此您可以安装一个信号处理程序来捕获它并设置一个标志,告诉您的例程做出适当的反应。
    • 在 Windows 中,操作系统调用结构化异常处理以将处理器异常转换为语言异常,您可以使用 C 中的 __try / __catch 块或 C++ 中的 try / catch 块来捕获该异常。
    • 更新:对于 Mac OS X,如 this answer 中所述,您应该能够使用来自 xmmintrin.h_MM_SET_EXCEPTION_MASK 启用/取消屏蔽异常,并且只要您使用默认编译器选项 (即,不要禁用 SSE),您应该能够使用 SIGFPE 捕获异常。

    (如果你好奇的话,我已经在this blog posting 中写了更多关于这个和其他 C 和 C++ 中的浮点问题。)

    【讨论】:

    • 这是一个很好的观点,我只是在玩这个,因为我很幸运,我在一个有 2 个平台特定问题的 Mac 上:gnu.org/software/hello/manual/gnulib/feenableexcept.htmllists.apple.com/archives/Darwin-dev/2006/Mar/msg00102.html
    • 我添加的链接中的信息似乎在我有限的测试中对我有用。
    • 感谢 mac OS X 链接,这是一个非常不规则的处理,因为它仅适用于 sse 类型(float 和 double),但不适用于 x87 特定的 long double。此外,启用异常是针对整个进程,而不是针对当前线程,这使得使用它变得困难。
    • 好点。我不知道还有什么可以尝试的,抱歉。据我所知,由于我远不是浮点专家,有什么特别的原因使用 fetestexcept 在事后检查异常不起作用?
    • 想象一下你正试图反转一个大矩阵,一旦明确它是不可逆的,你就想退出大计算。坚持到最后是浪费时间。
    【解决方案2】:

    C 和可能从它派生的大多数语言,如 C++ 或 python(尽管可能是间接访问)。期望低级语言有这样的支持可能是合理的。

    请参阅http://www.math.utah.edu/~beebe/software/ieee/#c-notes,其中有大量关于使用 IEEE 754 号码的脚本和说明。特别是of1.c 处理浮点异常。最后,来自http://grouper.ieee.org/groups/754/reading.html 的来源,其中包含大量有用的信息。

    【讨论】:

    • 你能再具体一点吗?我在文档中找不到这个,我找到了如何操作标志,但没有找到如何设置陷阱:opengroup.org/onlinepubs/000095399/basedefs/fenv.h.html
    • 感谢您的链接。在查看了 C 程序之后(我认为我看起来不错,但是在所有这些预处理器噪音中很难肯定),我没有看到这样暴露的陷阱。我只看到标志操纵。 SIG_FPE 处理程序似乎是一个平台的特殊情况。
    【解决方案3】:

    我不确定标准是什么,但我可以告诉你我从经验中看到的,因为它可能有用。我用 C++ 编写过代码,而 NaN 有时是我最糟糕的噩梦。它们默默地出现并通过计算一直传播到最后,直到我只有无用的输出。我经常不得不创建额外的代码来专门检测导致 NaN 的情况。我正在使用 Visual C++ 2008,所以我希望它会以这种方式遵循 IEEE 标准。

    【讨论】:

    • 是的,它完全是标准的。但是该标准定义了 3 个使用级别 1)传播 NaN 和 infs 2)您可以检查的标志 3)软件陷阱。也许您的使用太高级而无法保持默认行为。
    【解决方案4】:

    Maple 的编程语言有一个符合 IEEE-754 的数字模型,并且允许您根据需要设置自己的陷阱处理程序。以下是一些链接:

    Maple 的一个不常见的特性是默认浮点数是十进制(不是二进制)并且具有任意精度。如果要处理 64 位二进制浮点数,请将它们包装在 HFloat 中。例如,0.2 精确地表示十进制数,而 HFloat(0.2) 表示在 C 中将 0.2 分配给双精度数得到的相同数字。例如,通过运行可以明显看出这一点,

    a := HFloat(0.2);
    b := 0.2;
    evalf[20](a - b);
    

    这使用 20 位十进制数算术计算 ab 之间的差异,结果为 0.11E-16

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-28
      • 1970-01-01
      • 1970-01-01
      • 2012-06-30
      • 2011-04-19
      相关资源
      最近更新 更多