浮点数的二进制表示

引言

浮点数运算经常会给我们造成一定的困扰,比如在 c/java 中 16777216f16777217f 计算机认为是相等的,在 python 中 0.1+0.2 的结果为 0.30000000000000004 ,当然,我们可以简单的解释为是因为浮点数的不精准导致的,但是为什么会这样呢?浮点数在计算机中又是怎样存储的呢?

float f1=16777216;
float f2=16777217;
printf("%d\n",f1==f2);

基础

  1. 对于非常大(日地距离)或非常小(原子半径)的数据,工程师们喜欢使用科学计数法来表示,例如地球和太阳之间的距离是 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。
  2. 二进制转十进制,$ 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} $。
  3. 十进制转二进制,$ 1.5625_{10} $ = 对于整数部分,除2取余,逆序排列;对于小数部分,乘2取整,顺序排列

正文

当代大部分计算机和计算机程序在处理浮点数时所遵循的标准是ANSI/IEEE Std 754-1985,IEEE浮点数标准定义了两种基本的格式:以4个字节表示的单精度格式和以8个字节表示的双精度格式,下面我们以单精度为例。

单精度浮点数的4个字节分为三部分:

  • 1位的符号(0位正,1位负)
  • 8位的指数
  • 23位的有效数,对于二进制科学计数法的规范式,其有效数的小数点左边有且仅有一个1,因此在标准中这一位没有分配存储空间,也就是说,虽然有效数仅存储了23位,但其精度为24位
img

$ (-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

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

2人评论了“浮点数的二进制表示”