为什么计算机不善于处理小数

在学程序设计的时候,一定有很多的小伙伴 接触过 比如 C 语言 中 100 个 0.1 自增不等于 10的情况。
是啊是啊,超级迷啊。这次我们从二进制小数运算的原理 来解释一下。

我们知道 二进制数 1101 怎么转化成 10进制的数值
1 1×2^3 = 8
1 1×2^2 = 4
0 0x2^1 = 0
1 1×2^0 = 1
8 + 4 + 0 + 1 = 13

所以我们得知 二进制 1101 转化成 十进制数是 13

那么问题来了,像 1101.0011 这样的带有小数的呢?
其实依照刚刚上面的类推
运算是这样的
1 1×2^3 = 8
1 1×2^2 = 4
0 0x2^1 = 0
1 1×2^0 = 1
. ←这里是个小数点
0 0x2^-1 = 0
0 0x2^-2 = 0
1 1×2^-3 = 0.125
1 1×2^-4 = 0.0625
于是:
8 + 4 + 0 + 1 + 0 + 0 + 0.125 + 0.0625 = 13.1875
可以尝试的是这种运算方式时非常严谨的,在十进制中也是通用的!

所以我们很容易得知的是 有一些十进制数的小数是无法转换成二进制数

0.0000 — 0
0.0001 — 0.0625
0.0010 — 0.125
0.0011 — 0.1875
0.0100 — 0.25
… …
如此 0 的下一位就是 0.0625 这中间的小数就无法用小数点后4位的二进制数表示。
而 十进制数 0.1 转换成二进制也是 0.00011001100(的循环)

因为计算机的功能是有限的 无法正确表示的数值,最后都变成了近似值。
计算机遇到十进制数中的循环小数时,计算机就会根据变量数据类型所对应的长度将数值从中间阶段或者四舍五入。

如何避免计算机计算出错

既然说到这里,我更想知道如何避免这个错误,毕竟谁也不想出错嘛!
简单的说分为这样几种

  • 忽略掉
  • 用整数替代
  • BCD表示法

第一个就是 在一些情况下允许误差存在的话,可以不用考虑的。
第二个一般是 先转换成 整数再 除方 来求得小数
第三个是Binary Coded Decimal 是一种二进制数据的表示方法

即BCD代码。Binary-Coded Decimal‎,简称BCD,称BCD码或二-十进制代码,亦称二进码十进数。是一种二进制的数字编码形式,用二进制编码的十进制代码。这种编码形式利用了四个位元来储存一个十进制的数码,使二进制和十进制之间的转换得以快捷的进行。这种编码技巧,最常用于会计系统的设计里,因为会计制度经常需要对很长的数字串作准确的计算。相对于一般的浮点式记数法,采用BCD码,既可保存数值的精确度,又可免却使电脑作浮点运算时所耗费的时间。此外,对于其他需要高精确度的计算,BCD编码亦很常用。

发布者

ShellV

高中狗、喜欢前端、运维、AcgBag 动漫社区创始站长