c ++:在数学错误中创建实际错误而不是nan

Posted

技术标签:

【中文标题】c ++:在数学错误中创建实际错误而不是nan【英文标题】:c++: create actual error in math errors instead of nan 【发布时间】:2016-10-24 20:57:56 【问题描述】:

我有一个非常大的代码,很难调试。在某些情况下,它会给出nan 作为结果。

我知道它可能是在sqrt(-1) 之类的数学错误中产生的。但我无法发现错误。如果我可以在数学错误中产生错误,而不是 nan,我将能够很容易地发现错误。

我可以通过定义一个宏来实现吗?我想我在某处看到了这样的解决方案。

注意:我不想在每次数学运算后使用if(isnan(res)) exit(0);

【问题讨论】:

This page 在底部有关于启用从浮点环境异常中抛出 C++ 异常的说明(您必须在引发它们之前对其进行配置)。 【参考方案1】:

感谢chris,这是math error handling 的摘要。

这些浮点异常在cfenv 头文件中定义:FE_ALL_EXCEPTFE_DIVBYZEROFE_INEXACTFE_INVALIDFE_OVERFLOWFE_UNDERFLOW。这些名称是不言自明的。

我们可以使用fetestexcept 确定当前设置了哪些指定的浮点异常子集。我们可以使用feclearexcept 清除发生的异常列表。

下面是一段代码,它显示了我们如何确定引发的浮点异常:

C++11 标准:

#include <iostream>
#include <cfenv>
#include <cmath>

#pragma STDC FENV_ACCESS ON

volatile double zero = 0.0; // volatile not needed where FENV_ACCESS is supported
volatile double one = 1.0;  // volatile not needed where FENV_ACCESS is supported

int main()

    std::feclearexcept(FE_ALL_EXCEPT);
    std::cout <<  "1.0/0.0 = " << 1.0 / zero << '\n';
    if(std::fetestexcept(FE_DIVBYZERO)) 
        std::cout << "division by zero reported\n";
     else 
        std::cout << "divsion by zero not reported\n";
    

    std::feclearexcept(FE_ALL_EXCEPT);
    std::cout << "1.0/10 = " << one/10 << '\n';
    if(std::fetestexcept(FE_INEXACT)) 
        std::cout << "inexact result reported\n";
     else 
        std::cout << "inexact result not reported\n";
    

    std::feclearexcept(FE_ALL_EXCEPT);
    std::cout << "sqrt(-1) = " << std::sqrt(-1) << '\n';
    if(std::fetestexcept(FE_INVALID)) 
        std::cout << "invalid result reported\n";
     else 
        std::cout << "invalid result not reported\n";
    

在 C99 中:

#include <stdio.h>
#include <math.h>
#include <float.h>//for DBL_MIN and DBL_MAX
#include <fenv.h>

#pragma STDC FENV_ACCESS ON
void show_fe_exceptions(void)

    printf("exceptions raised:");
    if(fetestexcept(FE_DIVBYZERO)) printf(" FE_DIVBYZERO");
    if(fetestexcept(FE_INEXACT))   printf(" FE_INEXACT");
    if(fetestexcept(FE_INVALID))   printf(" FE_INVALID");
    if(fetestexcept(FE_OVERFLOW))  printf(" FE_OVERFLOW");
    if(fetestexcept(FE_UNDERFLOW)) printf(" FE_UNDERFLOW");
    feclearexcept(FE_ALL_EXCEPT);
    printf("\n");


int main(void)

    printf("MATH_ERREXCEPT is %s\n",
           math_errhandling & MATH_ERREXCEPT ? "set" : "not set");

    printf("0.0/0.0 = %f\n", 0.0/0.0);
    show_fe_exceptions();

    printf("1.0/0.0 = %f\n", 1.0/0.0);
    show_fe_exceptions();

    printf("1.0/10.0 = %f\n", 1.0/10.0);
    show_fe_exceptions();

    printf("sqrt(-1) = %f\n", sqrt(-1));
    show_fe_exceptions();

    printf("DBL_MAX*2.0 = %f\n", DBL_MAX*2.0);
    show_fe_exceptions();

    printf("nextafter(DBL_MIN/pow(2.0,52),0.0) = %.1f\n",
                      nextafter(DBL_MIN/pow(2.0,52),0.0));
    show_fe_exceptions();

【讨论】:

以上是关于c ++:在数学错误中创建实际错误而不是nan的主要内容,如果未能解决你的问题,请参考以下文章

为啥将字符串作为文件名而不是 char* 传递时出现错误?

在 Oracle PL/SQL 中创建触发器时如何解决“编译错误成功”错误?

Wamp 服务器错误 - php

在 localhost 的 php 中创建个性化的 404 错误页面

在Laravel中创建,更新或删除记录时识别sql错误的最佳方法

在C中创建文件会产生致命错误