C++-两个double类型的值相等采用其差值小于某个很小的值判断,这个很小的值怎么产生的?

发布于 2017-04-04 01:41:20 字数 711 浏览 1705 评论 2

C++中,double类型变量在计算机中存储的尾数是52bit,而按照规定,尾数最到位一定是1,那么也就是说52bit的尾数位能够表示的范围是
1.000....00(52个0)~1.111...111(52个1)

在本机上,做如下测试
double m=2.0123456789012344;double n=2.0123456789012345; 编译器认为m==n
double m=2.012345678901233;double n=2.012345678901234;编译器认为m!=n

因此,我认为小数点后的第14bit依然是精确的。
也就说52bit的二进制尾数位确保了十进制表示方法下,小数点后的14位依然精确。
那么,1.12345678901234和0.123456789012349999因为小数点后的数值前14位相等,所以这两个数也被计算机认为是相等的。

据此,bool equal(double a,double b){
if(abs(a-b)<0.000....001) // 0.000....001包含13个0
return true;
}

对于,网上提到abs(a-b)<非常小的数,这个数字可以定义为0.00000001就很不理解。
根据他们的理论,1.12345678和1.123456781就是相等的,然而实际存储情况看,它们并不相等。

你们是怎么看的?求教大家

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浮生未歇 2017-10-01 03:47:28

浮点数本来就不能精确的表达实数,即使是有限小数也不行,例如“432.121”这个小数,如果你计科导课程学的过关的话,可以试着把这个小数转换成浮点数,你会发现你是做不到的。
究其原因,

浮点数(floating-point number)是属于有理数中某特定子集的数的数字表示,在计算机用以近似表示任意某个实数。

摘自“维基百科”,所谓子集的意思就是浮点数只能表达有理数中有限的一部分。所以,在浮点数上追求相等意义不大,因为它本身就不能精确的表达数值。那我们应该怎么办?工程上的一般作法是先根据所需结果的精确位数计算出所需参与运算的字长,然后再根据指定相应的字长进行简化运算。那我们为什么认为1.12345678和1.123456781就是相等的?因为精度足够了,没有必要进行多余的计算。

至于误差产生的原因,我可以作下简单的推导

晚风撩人 2017-08-23 03:41:05

"小数点后的数值前14位相等,所以这两个数也被计算机认为是相等的" -- 我认为是不对的. 你应该了解了ieee754, 这个double值, 是用64个bit算出来的, 小数点后14位这个, 我觉得不靠谱(不过我也没法证明哈, 数学不咋地).

你在程序中, 得出这两个值相等, 应该是因为他们的 内部存储的64个bit是一样的.

double m=2.0123456789012344;double n=2.0123456789012345;
内存里都是:
0xb0f90592 0x40001948

这个和java里Double.equals()是一样的.

另外你说的, "网上提到abs(a-b)<非常小的数,这个数字可以定义为0.00000001就很不理解。根据他们的理论,1.12345678和1.123456781就是相等的,然而实际存储情况看,它们并不相等。" -- 这个看你的应用场景, 比如做一些数值计算, 不要求那么精确, 取一个合理的可以接收的误差范围即可. (比如我在测算房屋面积, 0.01厘米的误差可以忽略了吧?)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文