float.h

float.h

一背景知识
浮点算术非常复杂   很多小的处理器在硬件指令方面甚至不支持浮点算术   其他的则需要一个独立的协处理器来处理这种运算   只有最复杂的计算机才在硬件指令集中支持浮点运算
一般应用程序不需要浮点算术   其他可以通过软件来实现浮点运算  需要性能的降低和几千字节的额外代码
上溢和下溢
一个结果可能太大 不能在一台机器上表示   结果上溢可能导致终端 可能会产生一个特殊的编码值   或者会产生一个很 容易被误导的有效值的垃圾值    
一个结果可能太小而不能在一台机器上表示   但是在另一台机器上却可以表示  结果可能会导致终端  可能会被精确的0 代替
有效值丢失
把两个精确的数相乘后可能得到一般的有效值  把两个大小相近的数相减  可能会丢失大部分或者全部的有效值
上溢和下溢和有效值丢失对浮点算术来说是固有的
变化
浮点值的运算加法 所得的结果在一定程度上依赖于那两台机器的舍入方式 在某些场合下 得到一个快速的答案比得到一个尽可能
精确的答案要好得多
浮点型的描述
c标准通常描述定义足够多的术语来讨论浮点型的参变量 但是并没有说明如何得到一个正确的结果
float.h头文件补充已经存在的头文件limits.h 我们把那些可能对严格的数值运算程序员有用的每个参数都加入到float.h中
 
二 c标准的内容
float.h
float.h和limits.h  两个头文件定义了几个可以展开为各种范围和参数的宏
浮点类型的特征float.h
在一个模型的基础上定义   描述了浮点数字和一些值的表示方法   提供了一个实现浮点算术的信息   
s 符号+-1
b 指数表示的基数  一个大于1的整数
e 指数 一个值在e(min)和e(max)之间的整数
p 精度(b进制数的有效位数)
f(k) 比b小的非负整数 有效数字
一个规格化的浮点数x   如果x!=0  则f(1)>0  
 
 
FLT_ROUNTDS     浮点加法的舍入模式
FLT_RADIX 指数表示的基数
FLT_MANT_DIG 进制的浮点数的有效位数 p
...
三 float.h的使用
复杂的数值程序会用到    浮点算数的3个缺陷是上溢 下溢和有效值的丢失  以下有几种使用这些宏的方式  可以更加安全地执行double型算术运算  当然也适用于float和long double类型
 
上溢
为了避免上溢  一定要保证所有的值都不会超过DBL_MAX的数值
执行测试的时候 错误已经发生了  如果存储在y中的值太大了而不能表示   y可能会包含一个特殊的代码   dbl_max或者一个无用的值   由提供浮点算术的种类所决定
可以通过一个测试
if(x<log(DBL_MAX))
y=exp(x);
else
... /*HANDLE OVERFLOW*/
也可以通过使用一个相关的宏来避免计算log(DBL_MAX)
if(x<=FLT_MAX_10_EXP)
y=pow(10,x);
else
... /*HANDLE OVERLFOW*/
如果FLT_RADIX不等于10   此测试有必要  通常值为2   或者更少的情况为16   
函数ldexp使得通过2的幂来换算一个浮点数变得很容易   在FLT_RADIX等于2的普遍情况下   会是一个效率很高的操作
对于一个整型指数n来说
if(n<FLT_MAX_EXP)
y=ldexp(1.0,n);
else
... /*HANDLE OVERFLOW*/
当为数学库编写附加的函数时   很可能使用最后一个测试
 
下溢
为了避免下溢   一定要保证所有的值都大于等于DBL_MIN的数值  几乎所有的浮点实现都用0来代替一个过小而不能表示的值   只有当除以一个会产生下溢的值时  才会遇到麻烦。
测试
if(log(DBL_MIN)<=x)
y=exp(x)
else
.../*HANDLE UNDERFLOW*/
if(FLT_MIN10_EXP<=x)
y=pow(10,x);
else
.../*HANDLE UNDERFLOW*/
if(FLT_MIN_EXP<n)
y=ldexp(1.0,n);
else 
..../*HANDLE UNDERFLOW*/
 
有效值的丢失
当两个几乎相等的值相减的时候  就会发生有效值丢失   但是可以组织有效值的丢失  --把一个很小的数和一个很大的 数相加    一个浮点数表示只能保持一个确定的精度   
原文地址:https://www.cnblogs.com/dongguolei/p/7896461.html