【问题标题】:How do I force 0.0/0.0 to return zero instead of NaN in MIPSPro C compiler?如何在 MIPSPro C 编译器中强制 0.0/0.0 返回零而不是 NaN?
【发布时间】:2011-02-03 12:57:20
【问题描述】:

正如问题所述,我正在使用 MIPSPRo C 编译器,并且我有一个操作将为分子和 denom 都为零的某些数据集返回 NaN。如何防止这种情况发生?

【问题讨论】:

  • 0/0 根本不是一个数字,当然也不是0。为什么要它评估为一个数字?

标签: c nan


【解决方案1】:

在带有 MIPSPro 编译器的 SGI 系统上,您可以使用 sigfpe.h 中的工具以高精度设置各种浮点异常的处理。碰巧,零除以零就是这样一种情况:

#include <stdio.h>
#include <sigfpe.h>

int main (void) {
    float x = 0.0f;
    (void) printf("default %f / %f = %f\n", x, x, (x / x));
    invalidop_results_[_ZERO_DIV_ZERO] = _ZERO;
    handle_sigfpes(_ON, _EN_INVALID, 0, 0, 0);
    (void) printf("handled %f / %f = %f\n", x, x, (x / x));
    return 0;
}

使用中:


arkku@seven:~/test$ cc -version
MIPSpro Compilers: Version 7.3.1.3m
arkku@seven:~/test$ cc -o sigfpe sigfpe.c -lfpe
arkku@seven:~/test$ ./sigfpe
default 0.000000 / 0.000000 = nan0x7ffffe00
handled 0.000000 / 0.000000 = 0.000000

如您所见,设置_ZERO_DIV_ZERO 结果会更改相同除法的结果。同样,您可以处理常规除以零(例如,如果您不希望结果为无穷大)。

当然,这些都不是标准的;在每次除法之后检查 NaN 会更便携,甚至更好地在之前检查零。 C99 在fenv.h 中提供了对浮点环境的一些控制,但我认为没有任何适合于此的方法可用。无论如何,我的旧 MIPSPro 不支持 C99。

【讨论】:

    【解决方案2】:

    使用 if 子句?我也很好奇你为什么要忽略这种数学上的不可能性。您确定在这种情况下您的输入没有错误/没有意义吗?

    【讨论】:

    • 确定这不是毫无意义的,不。我正在做一个有限元求解器,偶尔会在边界周围,并且在 3d 网格的“角落”中,由于有人在这些边缘上指定零,因此分子和分母上会出现零
    • 我不知道如何处理这个问题,除了检查它。这个编译器的 Fortran 版本确实有一个选项允许您为 NaN 指定一个值,我认为是因为这个原因?
    • 通常正确的方法是忽略这些点。所以使用我建议的 if 子句来检查值是否为零。
    • 如果我们说的是标准 C,使用 if 将是最好的解决方案,但是当提问者指定 MIPSPro 时,它恰好支持这种特定情况...... =)
    • 很好看,+1。但是我仍然想知道为什么 Derek 似乎想“默默地忽略”这些案例。通常当你在数学中遇到这样的问题时,你的输入就有问题。
    【解决方案3】:

    如果您不介意引入一个小错误,则可以在分母上添加一个小值,假设您正在执行浮点运算。显然定义了一些小值:

    DBL_MIN 是最小的双精度数

    DBL_EPSILON 是最小的 double s.t。 x+DBL_EPSILON != x

    所以我会尝试

    #include <float.h>
    #define EPS DBL_MIN
    
    double divModified(double num, double denom) {
        return num / (denom + EPS);
    }
    

    【讨论】:

    • denom+DBL_MIN 应该足够好了。如果 denom 为 0,denom+DBL_MIN==DBL_MIN。对于几乎任何其他足够大的值 X(我应该猜到大于 2^-2047 的任何值?),X+DBL_MIN==X,所以结果应该不受影响。
    • 分母总是正好 DBL_MIN :)
    【解决方案4】:

    IEEE 754(浮点规范)表示 0.0/0.0 不是数字,即NaN。如果您希望它是其他任何东西,到目前为止,最好的方法是检测 if 子句中的操作数何时都为零并返回您宁愿给出的值。可能是这样的:

    #define WonkyDiv(a,b)  ((a)==0.0&&(b)==0.0 ? 0.0 : (a)/(b))
    
    float wonkyResult = WonkyDiv(numerator, denominator);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-02
      • 2021-05-23
      • 1970-01-01
      • 2013-04-03
      • 1970-01-01
      • 1970-01-01
      • 2018-07-16
      • 2018-05-20
      相关资源
      最近更新 更多