| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 936 人关注过本帖
标题:C语言检测计算产生subnormal值的函数是什么?
只看楼主 加入收藏
lchydp
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2021-5-4
结帖率:100%
收藏
已结贴  问题点数:5 回复次数:4 
C语言检测计算产生subnormal值的函数是什么?
大家好!在《C Primer Plus》中,作者提到,浮点数的运算可能会产生下溢(underflow),如果精度丢失,就会产生低于正常值(subnormal)的计算结果。并说明了C语言提供了检查计算是否会产生subnormal值的函数。但并未说明是哪个函数。我查到
https://cloud.
,按照这篇文章测试。如果运算产生了上溢和下溢,并未匹配到对应的宏。
程序代码:
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <fenv.h>

#pragma STDC FENV_ACCESS ON
void show_fe_exceptions(void)
{
    int result;
    printf("exceptions raised:");
    if (result = fetestexcept(FE_DIVBYZERO))
    {
        printf(" FE_DIVBYZERO\n");
        printf("result = %d\n", result);
    }
    else if (result = fetestexcept(FE_INEXACT))
    {
        printf(" FE_INEXACT\n");
        printf("result = %d\n", result);
    }
    else if (result = fetestexcept(FE_INVALID))
    {
        printf(" FE_INVALID\n");
        printf("result = %d\n", result);
    }
    else if (result = fetestexcept(FE_OVERFLOW))
    {
        printf(" FE_OVERFLOW\n");
        printf("result = %d\n", result);
    }
    else if (result = fetestexcept(FE_UNDERFLOW))
    {
        printf(" FE_UNDERFLOW\n");
        printf("result = %d\n", result);
    }
    else
    {
        printf(" no above expections\n");
        printf("result = %d\n", result);
    }
    feclearexcept(FE_ALL_EXCEPT);
    printf("\n");
}

int main(void)
{
    printf("MATH_ERREXCEPT is %s\n\n",
        math_errhandling & MATH_ERREXCEPT ? "set" : "not set");
    
    float toobig = 3.4E38 * 100.0f;
    printf("toobig = %e\n", toobig);///< 未产生上述异常,输出inf
    show_fe_exceptions();

    float toosmall = 1.0 * 3.4E-65565;
    printf("toosmall = %e\n", toosmall);///< 未产生上述异常,输出0.000000e+00
    show_fe_exceptions();

    return 0;
}

请问这是为什么呢?C语言检测计算产生subnormal值的函数究竟是哪个呢?

[此贴子已经被作者于2021-5-4 18:54编辑过]

搜索更多相关主题的帖子: printf 函数 result C语言 计算 
2021-05-04 18:48
lchydp
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2021-5-4
收藏
得分:0 
另外,上述文章中的宏FE_DIVBYZERO不知道什么时候能匹配到。如果除法的分母为0,是不能通过编译的,而分母是接近于0的数,也不能产生这个异常
程序代码:
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <fenv.h>

#pragma STDC FENV_ACCESS ON
void show_fe_exceptions(void)
{
    int result;
    printf("exceptions raised:");
    if (result = fetestexcept(FE_DIVBYZERO))
    {
        printf(" FE_DIVBYZERO\n");
        printf("result = %d\n", result);
    }
    else if (result = fetestexcept(FE_INEXACT))
    {
        printf(" FE_INEXACT\n");
        printf("result = %d\n", result);
    }
    else if (result = fetestexcept(FE_INVALID))
    {
        printf(" FE_INVALID\n");
        printf("result = %d\n", result);
    }
    else if (result = fetestexcept(FE_OVERFLOW))
    {
        printf(" FE_OVERFLOW\n");
        printf("result = %d\n", result);
    }
    else if (result = fetestexcept(FE_UNDERFLOW))
    {
        printf(" FE_UNDERFLOW\n");
        printf("result = %d\n", result);
    }
    else
    {
        printf(" no above expections\n");
        printf("result = %d\n", result);
    }
    feclearexcept(FE_ALL_EXCEPT);
    printf("\n");
}

int main(void)
{
    printf("MATH_ERREXCEPT is %s\n\n",
        math_errhandling & MATH_ERREXCEPT ? "set" : "not set");
    
    /*printf("0.0/0.0 = %f\n", 0.0 / 0.0);///< 编译不能通过,错误:C2124,被零除或对零求模
    show_fe_exceptions();

    printf("1.0/0.0 = %f\n", 1.0 / 0.0);///< 编译不能通过,错误:C2124,被零除或对零求模
    show_fe_exceptions();*/

    printf("0.0/DBL_MIN = %f\n", 0.0 / DBL_MIN);///< 未产生上述异常,0.0/DBL_MIN = 0.000000
    show_fe_exceptions();

    printf("0.0/(DBL_MIN * -1) = %f\n", 0.0 / (DBL_MIN * -1));///< 未产生上述异常,0.0/(DBL_MIN * -1) = -0.000000
    show_fe_exceptions();

    return 0;
}


[此贴子已经被作者于2021-5-4 18:54编辑过]

2021-05-04 18:53
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9007
专家分:53942
注 册:2011-1-18
收藏
得分:5 
https://en.

上面链接的代码,我试过,可以
2021-05-04 19:46
lchydp
Rank: 1
等 级:新手上路
帖 子:3
专家分:0
注 册:2021-5-4
收藏
得分:0 
谢谢!但是我试了,DBL_MAX*2.0没有产生任何异常。请问您用的什么编译器?我用的VS2015。另外我的示例代码不应该用if...else if,因为一个运算可能会产生多个异常。还有show_fe_exceptions的最后应该清理异常。否则下次再调该函数,还会显示仍在内存中的,上次调用show_fe_exceptions产生的异常
2021-05-09 19:21
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9007
专家分:53942
注 册:2011-1-18
收藏
得分:0 
回复 4楼 lchydp
那你将 #pragma STDC FENV_ACCESS ON
改为 #pragma fenv_access( on )
试试

程序代码:
#include <stdio.h>
#include <fenv.h>
#include <float.h>
//#pragma STDC FENV_ACCESS ON
#pragma fenv_access( on )

 
void show_fe_exceptions(void)
{
    printf("current 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");
    if(fetestexcept(FE_ALL_EXCEPT)==0) printf(" none");
    printf("\n");
}

 
int main(void)
{
    feclearexcept(FE_ALL_EXCEPT);
    show_fe_exceptions();

 
    printf("DBL_MAX*2.0 = %f\n", DBL_MAX*2.0);    /* FE_INEXACT FE_OVERFLOW  */
    show_fe_exceptions();
}


current exceptions raised:  none
DBL_MAX*2.0 = inf
current exceptions raised:  FE_INEXACT FE_OVERFLOW
2021-05-10 08:53
快速回复:C语言检测计算产生subnormal值的函数是什么?
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.018826 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved