关于float, double的精度问题

本文探讨了计算机中浮点数的存储原理,解释了为何某些十进制数如0.1和0.15在二进制表示下无法精确表示,并提供了在编程中比较浮点数时的有效解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在计算机中, 我们的real number 是以二进制的方式存储的。 而且存储一个float或者一个double类型的数据的存储空间是固定的, float一般是4个字节, double是8个字节。于是这就涉及到了将十进制转换为二进制的过程中, 可能一个十进制的数对应的二进制的表示的位数是无穷大的。 例如十进制数字0.1 和 0.15都不能在计算机中精确的表示。 除非我们使用无穷多的位数去表示0.1 或者0.15, 1.0/3.0等这样的数数字。

bottom line:、

Never use == to compare two floating point numbers


下面看如下例:

#include <iostream>

using namespace std;

int main()
{
    cout << 0.15 << endl;
    cout << 0.1 << endl;

    if (0.3 == 3 * 0.1)
        cout << "YES" << endl;
    else
        cout << "NOT" << endl;
    return 0;
}

运行结果:



问题, 既然0.15无法精确的表示, 为什么仍然可以精确输出来的?

下面是解答:



当我们迫切需要比较两个double的数值该咋办呢?

The message is that some floating point numbers cannot always be represented exactly, so comparisons don't always do what you'd like them to do. In other words, if the computer actually multiplies 10.0 by 1.0/10.0, it might not exactly get 1.0 back.

That's the problem. Now here's the solution: be very careful when comparing floating point numbers for equality (or when doing other things with floating point numbers; e.g., finding the average of two floating point numbers seems simple but to do it right requires an if/else with at least three cases).

Here's the wrong way to do it:

void dubious(double x, double y)
{
  ...
  if (x == y)  // Dubious!
    foo();
  ...
}
If what you really want is to make sure they're "very close" to each other (e.g., if variable a contains the value 1.0 / 10.0 and you want to see if (10*a == 1)), you'll probably want to do something fancier than the above:
void smarter(double x, double y)
{
  ...
  if (isEqual(x, y))  // Smarter!
    foo();
  ...
}
There are many ways to define the isEqual() function, including:
#include <cmath>  /* for std::abs(double) */

inline bool isEqual(double x, double y)
{
  const double epsilon = /* some small number such as 1e-5 */;
  return std::abs(x - y) <= epsilon * std::abs(x);
  // see Knuth section 4.2.2 pages 217-218
}
Note: the above solution is not completely symmetric, meaning it is possible for isEqual(x,y) != isEqual(y,x). From a practical standpoint, does not usually occur when the magnitudes of x and y are significantly larger than epsilon, but your mileage may vary.


另外: 补充一下float和double的区别:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值