引言
浮点数运算经常会给我们造成一定的困扰,比如在 c/java 中 16777216f
和 16777217f
计算机认为是相等的,在 python 中 0.1+0.2
的结果为 0.30000000000000004
,当然,我们可以简单的解释为是因为浮点数的不精准导致的,但是为什么会这样呢?浮点数在计算机中又是怎样存储的呢?
float f1=16777216;
float f2=16777217;
printf("%d\n",f1==f2);
基础
- 对于非常大(日地距离)或非常小(原子半径)的数据,工程师们喜欢使用科学计数法来表示,例如地球和太阳之间的距离是 490,000,000,000 英尺写做 $ 4.9 \times 10^{11} = 49 \times 10^{10} = 0.49 \times 10^{12} $,其中4.9称为有效数,为了便于操作一般规定有效数的取值范围大于等于1且小于10,同样,对于2进制小数$ 101.1101 = 1.011101 \times 2^2 $,有趣的是在规范化的二进制浮点数中,小数点左边只有一个1。
- 二进制转十进制,$ 1.1001_2 = 1 \times 2^0 + 1 \times 2^{-1} + 0 \times 2^{-2} + 0 \times 2^{-3} + 1 \times 2^{-4} = 1.5625_{10} $。
- 十进制转二进制,$ 1.5625_{10} $ = 对于整数部分,除2取余,逆序排列;对于小数部分,乘2取整,顺序排列。
正文
当代大部分计算机和计算机程序在处理浮点数时所遵循的标准是ANSI/IEEE Std 754-1985,IEEE浮点数标准定义了两种基本的格式:以4个字节表示的单精度格式和以8个字节表示的双精度格式,下面我们以单精度为例。
单精度浮点数的4个字节分为三部分:
- 1位的符号(0位正,1位负)
- 8位的指数
- 23位的有效数,对于二进制科学计数法的规范式,其有效数的小数点左边有且仅有一个1,因此在标准中这一位没有分配存储空间,也就是说,虽然有效数仅存储了23位,但其精度为24位

$ (-1)^s \times 1.f_2 \times 2^{e-127} $,那么对于一个特定的数,就可以用s(符号),e(指数),一级f(有效数)来描述。
浮点数的存储的思想类似于科学计数法,例如十进制1.1的单精度描述为:0-01111111-00011001100110011001101,其中s为0,e为$ 01111111_2 = 127_{10} $,f为$ 00011001100110011001101_2 = 838861_{10} $
那它是怎么转换的呢?
二进制转十进制
带入$ (-1)^s \times 1.f_2 \times 2^{e-127} $,注意f为2进制形式
$ (-1)^0 \times 1.00011001100110011001101_2 \times 2^0 $ = 1.100000023841858
十进制转二进制
以1.1为例
- 1.1为正数,所以s = 0
- $ 2^0 \lt 1.1 \lt 2^1 $,所以e – 127 = 0
- 1.1转二进制小数为1.00011001100110011001101,所以f = 00011001100110011001101
this is a comment
this is a reply