首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >为什么计算机计算小数时会出错?

为什么计算机计算小数时会出错?

作者头像
Lihua奏
发布2026-06-23 20:32:21
发布2026-06-23 20:32:21
1270
举报

为什么计算机计算小数时会出错?

如果将 0.1 累加 100 次,结果等于 10 吗?

代码语言:javascript
复制
#include <stdio.h>

int main() {
    float sum;
    int i;

    // 将用来保存累加结果的变量清零
    sum = 0;

    // 将 0.1 累加 100 次
    for (i = 1; i <= 100; i++) {
        sum += 0.1;
    }

    // 显示结果
    printf("%f\n", sum);
    return 0;
}

在这里,他的结果等于 10.000002

为什么?来看二进制如何表示小数

举例:计算 1011.0011

前面知道 位权

  • 1011 整数部分的位权,第1位是 2 的 0 次幂,第2位是 2 的 1 次幂,以此类推
  • .0011 小数部分的位权,第1位是 2 的 -1 次幂,第2位是 2 的 -2 次幂,以此类推

图中4位二进制小数能表示的数值范围是 0.0000~0.1111

  • 0.0000 | 0
  • 0.0001 | 0.0625
  • 0.0010 | 0.125
  • 0.0011 | 0.1875
  • 0.0100 | 0.25 以此类推...

那么你给它一个十进制数 0.1,它如何表示?它无法通过 2 的负整数次幂相加来刚好凑出 0.1,最终会得到一个循环小数。上面的例子会得到 0.00011001100…(之后 1100 不断重复)

为什么?

目标:拿到 0.1 1/2 = 0.5 太大了,不取 1/4 = 0.25 太大了,不取 1/8 = 0.125 太大了,不取 1/16 = 0.0625 取! 剩余 0.1 - 0.0625 = 0.0375 1/32 = 0.03125 取! 剩余 0.0375 - 0.03125 = 0.00625 1/64 = 0.015625 太大了,不取 1/128 = 0.0078125 太大了,不取 1/256 = 0.00390625 取! 剩余 ...

为什么有些十进制小数用二进制表示时,会出问题?

因为一个小数能不能被二进制精确表示,关键看它化成分数以后,分母里是不是只剩下 2。

如何去判断能否被二进制精确表示? 以 0.375 举例

  1. 化为分数: 0.375 = 3/8
  2. 看分母: 8 = 2 × 2 × 2,分母里只有 2,所以它可以被二进制精确表示

反过来,0.1 = 1/10,而 10 = 2 × 5。分母里除了 2 还有 5,所以它用二进制就表示不完。

接下来是浮点数

常见的有

  • double(双精度浮点型)
  • float(单精度浮点型)

浮点数你可以先理解成,它把一个数拆成符号、尾数、基数和指数这4个部分来表示

  1. 符号: 用 "1" 来表示负数,用 "0" 来表示正数或者 0
  2. 尾数: 也称为有效数字,它保存了数字的主要有效位
  3. 基数: 即进制,二进制的基数为 2
  4. 指数: 表示小数点的实际位置,决定了数值的范围

那么,如何去避免计算机计算出错呢?两种方法

  1. 整数替代小数: 0.1 不是转换不了吗?那我用 1 先累加,再除以 10,结果就正确了
代码语言:javascript
复制
#include <stdio.h>

int main() {
    // int 是整数数据类型
    int sum;
    int i;

    // 将用来保存累加结果的变量清零
    sum = 0;

    // 将 1 累加 100 次
    for (i = 1; i <= 100; i++) {
        sum += 1;
    }

    // 将结果除以 10
    sum /= 10;

    // 显示结果
    printf("%d\n", sum);
    return 0;
}
  1. 回避策略: 意思就是允许一个很小的误差范围。100 个 0.1 毫米,理论计算结果为 10,但实际结果可能是 10.000002,结果相差不大,很多时候几乎可以忽略(但十分严谨的地方还是别这样)

二进制与十六进制

二进制在计算机里很有用,因为它和底层电路的状态很接近,但缺点是位数太长,看起来费劲

那么 4 位二进制刚好等于 1 位十六进制数,例如

  • 32 位的二进制数 00111101110011001100110011001101 就等价于
  • 8 位十六进制数 3DCCCCCD

总结:

说到底,问题并不是计算机不会算,而是有些十进制小数本身就没法用有限位的二进制精确表示。

所以很多时候,误差不是算错了,而是存的时候就已经只能存一个接近值。

这也提醒我们,在看待浮点数的时候,不能把它当成数学里的实数,而要把它当成一种“有限精度的近似表示”。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-06-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Lihua奏 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么计算机计算小数时会出错?
    • 总结:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档