• 转:浮点数环境 cfenv(fenv.h)


    转:浮点数环境 cfenv(fenv.h)

    https://blog.csdn.net/lion_hbeu/article/details/24013095

    在编写高精度浮点运算程序时,需要对浮点环境进行控制并捕获浮点环境异常。cfenv头文件定义了对浮点环境控制及异常相关的函数和宏。

    注记 

     FENV_ACCESS

    #pragma STDC FENV_ACCESS on //设置该参数表示可以访问浮点运算异常的状态值

    #pragma STDC FENV_ACCESS off //设置该参数表示禁止访问浮点运算异常的状态值

    浮点数异常处理 

    函数

    /* 清除EXCEPTS表示的异常状态  */  

    int feclearexcept (int __excepts);

    /* 产生由EXCEPTS表示的异常 */  

    int feraiseexcept (int __excepts) ;

    /* 将实现定义的异常标志EXCEPTS保存到FLAGP所指的对象中 */  

     int fegetexceptflag (fexcept_t *__flagp, int __excepts) ; 

    /* 根把EXCEPTS异常标志设置为FLAGP所指对象中的值 */  

    int fesetexceptflag (__const fexcept_t *__flagp, int __excepts) ; 

    /* 确定EXCEPTS指示的各个异常中有哪个异常子集被设置了 */  

    int fetestexcept (int __excepts) ;

    宏(int类型)

     FE_INEXACT       精度丢失 

     FE_DIVBYZERO     除数为0 

     FE_UNDERFLOW     结果向下溢出 

     FE_OVERFLOW      结果向上溢出 

     FE_INVALID       无效的运算 

     FE_ALL_EXCEPT    所有被支持的异常的按位或

    示例1

        #include <stdio.h> /* printf */
        #include <fenv.h> /* fegetround, FE_* */
        #include <math.h> /* rint */
    
    void show_all_except(void);
    int main () {    show_all_except();   double d = 1e-40;    float f;    f = d;//这种精度丢失在编译过程中编译器编译不会提示,运行也没有问题    show_all_except();    return 0; } void show_all_except(void) {    //设置该参数表示可以访问浮点运算异常的状态值    #pragma STDC FENV_ACCESS ON    //获取所有可能的异常    int res = fetestexcept(FE_ALL_EXCEPT);    printf( "Status: " );    if(res & FE_INEXACT)//判断是否有精度损失的异常    {      printf( " inexact ");    }   
      
    if(res & FE_UNDERFLOW)//判断是否有下溢    {      printf( " underflow ");    }
      
    if(res & FE_OVERFLOW)//判断是否有上溢    {      printf( " overflow ");    }
        
    if(res & FE_DIVBYZERO)//判断是否有被0除    {      printf( " zero-divide ");    }

        if
    (res & FE_INVALID)//判断是否有不合法的浮点运算   {      printf( " invalid ");   }
    printf(
    " "); }

    运行结果

    1. Status:
    2. Status: inexact underflow

    高精度编程时,可以通过这些函数检查是否存在异常,并进行相应处理。

    舍入控制 

    函数

    /* 获得当前的舍入方向,表示为一个舍入方向宏值  */  

    int fegetround (void) ;

    /* 设置舍入方向,成功时返回0  */  

    int fesetround (int __rounding_direction) ;

    宏(int类型)

    FE_TONEAREST     最近舍入 
    FE_UPWARD        向正无穷大(+Inf)舍入 
    FE_DOWNWARD      向负无穷大(-Inf)舍入 
    FE_TOWARDZERO    向0舍入

    示例2

        #include <stdio.h> /* printf */
        #include <fenv.h> /* fegetround, FE_* */
        #include <math.h> /* rint */
    
        void printfRounding();
        int main ()
        {
            printfRounding();
            printf ( "rint (2.49) = %.1f
    ", rint(2.49) );
            printf ( "rint (3.50) = %.1f
    ", rint(3.50) );
            fesetround(FE_TOWARDZERO);
            printfRounding();
            printf ( "rint (2.49) = %.1f
    ", rint(2.49) );
            printf ( "rint (3.50) = %.1f
    ", rint(3.50) );
        
            return 0;
        }
    
        void printfRounding()
        {
            printf ("now rounding using: ");
            switch (fegetround()) {
            case FE_DOWNWARD: printf ("downward"); break;
            case FE_TONEAREST: printf ("to-nearest"); break;
            case FE_TOWARDZERO: printf ("toward-zero"); break;
            case FE_UPWARD: printf ("upward"); break;
            default: printf ("unknown");
            printf("
    ");
        }

    运行结果:

    1. now rounding using: to-nearest
    2. rint (2.49) = 2.0
    3. rint (3.50) = 4.0
    4. now rounding using: toward-zero
    5. rint (2.49) = 2.0
    6. rint (3.50) = 3.0

     浮点数环境

    函数

    /* 获取当前的浮点数环境,并保存在ENVP所指的对象中 */  
    int fegetenv (fenv_t *__envp) ; 
    /* 设置浮点数环境 */  
    int fesetenv (__const fenv_t *__envp);
    /* 将当前浮点数环境保存到ENVP所指对象中,清除异常标志,然后安装一个无异常的浮点数环境 */  
    int feholdexcept (fenv_t *__envp) ; 
    /*没整明白*/

    int feupdateenv (__const fenv_t *__envp) ;

    类型

    fenv_t   表示浮点数环境的类型 

    fexcept_t    表示浮点数异常标志(这个标志保存了浮点数的状态)的类型

    宏(fenv_t *指针类型)

    FE_DFL_ENV  表示浮点数环境的缺省值(用于需要fenv_t参数的函数中)

    示例3:(本示例中用到了两个打印函数分别在示例1、示例2中定义)

        #include <stdio.h> /* printf */
        #include <fenv.h> /* fegetround, FE_* */
        #include <math.h> /* rint */
    
        void printfRounding();
        void show_all_except(void);
    
        int main ()
        {
            fenv_t fe;
            printfRounding();//打印当前Rounding规则
            show_all_except();//打印当前异常状态
    
            fesetround(FE_TOWARDZERO);//设置Rounding规则为向0靠近
            feraiseexcept(FE_INEXACT);//注册一个精度丢失异常
            printfRounding();//重新打印当前Rounding规则
            show_all_except();//重新打印当前异常状态
    
            fegetenv(&fe);//获取当前浮点环境
            fesetenv(FE_DFL_ENV);//设置浮点环境为默认值
            printfRounding();//重新打印当前Rounding规则
            show_all_except();//重新打印当前异常状态
    
            fesetenv(&fe);//设置浮点环境为上次保存的浮点环境
            printfRounding();//重新打印当前Rounding规则
            show_all_except();//重新打印当前异常状态
    
            feraiseexcept(FE_OVERFLOW);//注册一个结果向上溢出异常
            feholdexcept(&fe);//保存当前浮点环境,并清除所有异常
            printfRounding();//重新打印当前Rounding规则
            show_all_except();//重新打印当前异常状态
    
            fesetenv(&fe);//设置浮点环境为上次保存的浮点环境
            printfRounding();//重新打印当前Rounding规则
            show_all_except();//重新打印当前异常状态
    
            return 0;
        }

    运行结果

      1. now rounding using: to-nearest
      2. Status:
      3. now rounding using: toward-zero
      4. Status: inexact
      5. now rounding using: to-nearest
      6. Status:
      7. now rounding using: toward-zero
      8. Status: inexact
      9. now rounding using: toward-zero
      10. Status:
      11. now rounding using: toward-zero
      12. Status: inexact overflow
  • 相关阅读:
    C#操作OFFICE一(EXCEL)
    json的使用二(转)
    xpath简介(转载)
    使用LogParser分析IIS网站日志
    WCF Data Contract KnownTypeAttribute转载
    ExtJs中同一个URL构造多个Ext.data.JsonStore 转载
    转载Ext.form.formPanel 与服务器交互 初始化表单
    oracle表数据误删恢复
    JavaScript基础之Array函数
    Json格式类的转换相关代码转载
  • 原文地址:https://www.cnblogs.com/igfirstblog/p/9412541.html
Copyright © 2020-2023  润新知