浮点型数据的比较2010-04-16 12:15应注意排列顺序

2010-04-16 12:15

应注意排列顺序

=在前,=的判断条件是abs(a-b)<0.001,而不是简单的==比较

<在后。

这样比较安全

 

附上一段引文:

IEEE标准:
float的定义为:指数8位,尾数23位, 还有一位表示正负。
double的定义为:指数11位,尾数52为,还有一位表示正负。

如果a,b为接近最大表示数时(float是3.4E38),c接近负的最大表示数时,a+b将要溢出,而(a+c)+b不会溢出。如上所说,这种条件下是不是(a+b)+c 就不等于 (a+c)+b?答案却是相等。

C语言进行float操作时,要进行类型提升,float将转化为double进行运算,显然,在doulbe
精度中,刚才的情况不会发生溢出,答案是相等的。

更深一步思考,doulbe类型的a,b,c在数值接近最大值时 (a+b)+c 与 (a+c)+b的关系是什么?
答案也很有趣,在X86平台上,INTEL提供扩展的double精度,使用12个字节表示一个double,
因此,在IEEE表示的double数溢出的情况下,INTEL平台上还是不溢出,还是相等!但在其他
的ISA平台上,结果不能保证这一点。

因此本题目(这对float)的答案是相等。   

例二:

目前最优的方案是做差。
if (fabs(result1 - result2) < FLT_EPSILON)
printf("equals/n");

而这种 if(!(a>b||a<b)) 是绝对不起作用的。如果这个返回 true 了,那实际上你直接用 == 也能返回 true。
下面有一个例子,有兴趣的可以试试看,用到了一个初中的2项式展开:
(a + b)^2 = a^2 + 2 * a * b + b^2
数学上等号两边的运算式等价的,但是如果用计算机计算,两种方法会出现误差。
这个例子包含了几种方法,大家可以看看效果

#include "stdafx.h"
#include <float.h>
#include <math.h>

int main(int argc, char* argv[])
{
volatile double a = 321.423, b = 948.0394;
double result1, result2;

result1 = pow((a + b), 2.0);
result2 = pow(a, 2.0) + 2.0 * a * b + pow(b, 2.0);

if (fabs(result1 - result2) < FLT_EPSILON)
printf("fabs returns equals/n");

if ( ! (result1 < result2 || result1 > result2))
printf("That's funny!/n");

if (result1 == result2)
printf("result1 == result2/n");
else if (result1 > result2)
printf("result1 > result2/n");
else if (result1 < result2)
printf("result1 < result2/n");
else
printf("That's funny too!/n");

return 0;
}   

FLT_EPSILON

FLT_EPSILON用于float类型。
它是满足 x+1.0不等于1.0的最小的正数

For EPSILON, you can use the constants FLT_EPSILON, which is defined for float as 1.192092896e-07F, or DBL_EPSILON, which is defined for double as 2.2204460492503131e-016. You need to include float.h for these constants. These constants are defined as the smallest positive number x, such that x+1.0 is not equal to 1.0. Because this is a very small number, you should employ user-defined tolerance for calculations involving very large numbers.

http://hi.baidu.com/liguosheng83/blog/item/de3a5795deba5f047af4806f.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值