浮点数环境 cfenv(fenv.h)

在编写高精度浮点运算程序时,需要对浮点环境进行控制并捕获浮点环境异常。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( " \n ");  
} 

运行结果

Status:
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\n", rint(2.49) );
	printf ( "rint (3.50) = %.1f\n", rint(3.50) );
	fesetround(FE_TOWARDZERO);
	printfRounding();
	printf ( "rint (2.49) = %.1f\n", rint(2.49) );
	printf ( "rint (3.50) = %.1f\n", 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("\n");
}
运行结果:

now rounding using: to-nearest
rint (2.49) = 2.0
rint (3.50) = 4.0
now rounding using: toward-zero
rint (2.49) = 2.0
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;
}
运行结果

now rounding using: to-nearest
Status:
 now rounding using: toward-zero
Status:  inexact
 now rounding using: to-nearest
Status:
 now rounding using: toward-zero
Status:  inexact
 now rounding using: toward-zero
Status:
 now rounding using: toward-zero
Status:  inexact  overflow




  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值