---
slug: double
lesson: 9
chapter: 2
chapterTitle: 变量
title: 为什么 0.1 + 0.2 不等于 0.3？浮点数与精度
description: C++ 用 double 装小数，但 0.1 + 0.2 == 0.3 的结果是假。原因是小数用二进制存储，0.1 和 0.2 都存不下精确值。本课用可在线运行的示例验证这个现象，并给出正确的浮点比较写法。
code: |
  #include <iostream>
  using namespace std;

  int main() {
      double a = 0.1;
      double b = 0.2;
      double c = a + b;
      cout << c << endl;
      cout << (c == 0.3) << endl;
      return 0;
  }
faq:
  - q: 为什么 0.1 + 0.2 不等于 0.3？
    a: 小数在计算机里用二进制存储，0.1 和 0.2 的二进制是无限循环小数，只能存近似值。两个近似值相加得到 0.30000000000000004，与 0.3 不完全相等。
  - q: float 和 double 有什么区别？
    a: 都是小数类型。float 约 7 位有效数字，double 约 15 位。日常一律用 double，float 只在对内存敏感的大规模数据场景使用。
  - q: 浮点数应该怎么比较相等？
    a: 不要用 ==。判断两个浮点数是否"足够接近"：相减取绝对值，小于一个很小的数（如 1e-9）即视为相等。
---

<div class="answer">
0.1 + 0.2 的真实结果是 0.30000000000000004，与 0.3 比较相等得到"假"。
原因：小数按二进制存储，0.1、0.2 都只能是近似值。浮点比较不要用 ==，
要判断两数之差的绝对值是否足够小。
</div>

## double：装小数的类型

`double` 是小数（浮点数）类型，约 15 位有效数字，日常使用一律选它。`float` 精度只有约 7 位，入门阶段不需要碰。

## 一个反直觉的事实

```cpp
double a = 0.1;
double b = 0.2;
double c = a + b;
cout << c << endl;          // 看起来是 0.3
cout << (c == 0.3) << endl; // 输出 0（假）
```

小数在计算机里按**二进制**存储。十进制的 0.1 写成二进制是无限循环小数，存不下精确值，只能存一个非常接近的近似值——0.2 同理。两个近似值相加，得到的是 **0.30000000000000004**，与 0.3 差一丁点，`==` 比较结果是假。

cout 默认只显示 6 位有效数字，把 0.30000000000000004 显示成了 `0.3`——输出的"看起来对"，掩盖了存储的"实际不对"。

## 正确的比较方法

浮点数之间不用 `==`，改判"差得够不够小"：

```cpp
#include <cmath>
bool equal = fabs(c - 0.3) < 1e-9;   // 相差小于 0.000000001 视为相等
```

`fabs` 是绝对值函数，`1e-9` 是科学计数法表示的 0.000000001。

## 可视化观察

在 CppStudio 中打开本课示例，点击播放：

1. a、b、c 依次出现在监视区，执行加法后可以暂停，核对 c 的值；
2. 第一条 cout 输出 `0.3`——看起来一切正常；
3. 第二条 cout 输出 `0`——比较结果是假。两行输出放在一起，就是浮点精度问题最直观的演示。

## 常见错误

- **用 == 比较浮点数**：刚算出来"相等"的两个值，换一组数就不等了，一律改用差值判断；
- **误以为输出值就是真实值**：cout 默认只显示 6 位，真实存储值可能更长；
- **整数小数混用**：`double d = 1 / 2;` 先得整数 0 再转成 0.0，应写 `1.0 / 2`（承接上一课整数除法）。

下一课：char 与 bool——字符其实是一个数字，真假值也有自己的类型。
