9

为了教育目的,我想玩这些陷阱。

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

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

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

4

4 回答 4

3

据我所知,在 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,如本答案中所述,您应该能够使用_MM_SET_EXCEPTION_MASKfrom启用/取消屏蔽异常xmmintrin.h,并且只要您使用默认编译器选项(即,不要禁用 SSE),您应该能够使用 SIGFPE 捕获异常。

(如果你好奇的话,我在这篇博文中写了更多关于 C 和 C++ 中的这个和其他浮点问题的文章。)

于 2009-03-31T01:04:44.053 回答
0

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

于 2009-03-31T01:08:37.397 回答
0

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,其中包含一堆有用的信息。

于 2009-03-30T21:27:14.403 回答
0

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

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

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

a这将计算和使用 20 位十进制数字算术之间的差异b,结果为0.11E-16.

于 2013-10-16T18:43:28.777 回答