二进制的手工计算, 以及计算机的浮点数存储

十进制转二进制的计算

1. 整数部分
 按二进制数的定义, 将十进制转为二进制实际上就是将十进制拆分为用2的级数表示的序列, 计算方法实际上就是在模拟程序的处理方式: 将二进制不断地">" (shift right, 右移), 舍掉小数部分, 记下每次个位的值, 就能得到二进制的序列. 举例, 计算201的二进制序列

201 -> 1 //除2为100, 余1
100 -> 0 //除2为50, 余0
50  -> 0 //除2为25, 余0
25  -> 1 //除2为12, 余1
12  -> 0 //除2为6, 余0
6   -> 0 //除2为3, 余0
3   -> 1 //除2为1, 余1
1   -> 1 //除2为0, 余1
    -> 11001001 //按倒序排列即得到最终序列

2. 小数部分
 计算机中记录浮点数的小数部分, 实际上也是将小数部分分解为2的级数表示的序列, 计算方法是将二进制不断地"<"(shift left, 左移), 舍掉整数部分, 记下每次个位出现的0和1, 就能得到二进制的序列. 举例, 计算0.2的二进制序列

0.2 -> 0 // 乘2, 未满1, 余0.4
0.4 -> 0 // 乘2, 未满1, 余0.8
0.8 -> 1 // 乘2, 满1, 余0.6
0.6 -> 1 // 乘2, 满1, 余0.2
0.2 -> 0 // 乘2, 未满1, 余0.4
0.4 -> 0 // 从此进入循环
0.8 -> 1
0.6 -> 1
0.2 -> 0
0.4 -> 0
...
    -> 0.0011001100110011... // 按正序即得最终序列

计算机中浮点数的存储

计算机中的浮点数使用的是 IEEE 754 (IEEE二进位浮点数算术标准, IEEE Standard for Floating-Point Arithmetic), 这里有一个很形象的演示页面说明计算机是如何存储浮点数的 https://www.h-schmidt.net/FloatConverter/IEEE754.html

float(单精度浮点数)为4个字节, 其中1位表示符号Sign, 8位表示指数Exponent,23位表示尾数(Mantissa, 小数部分)
double(双精度浮点数)为8个字节, 其中1位表示符号, 11位表示指数, 52位表示尾数, IEEE 浮点值的格式如下图所示

三个组成部分:

Sign: 表示浮点数是正数还是负数, 0表示正数,1表示负数

Exponent: 指数部分, 类似于科学技术法中的M*10^N中的N,只不过这里是以2为底数而不是10。需要注意的是,这部分中是以2^7-1即127,也即01111111代表2^0,转换时需要根据127作偏移调整, 例如指数为2时, 这部分的值就是127+2=129. 在double型中, 指数偏移值是1023. 举例: 对于十进制数7.7510, 其二进制为 0111.112 = 1.11112 x 22, 其指数为2, 加上偏移量就是129; 对于十进制数 0.12510, 其二进制为0.0012 = 1.02 x 2-3, 其指数为-3, 加上偏移量就是124.

Mantissa: 基数部分, 浮点数具体数值的实际表示.

浮点数的精度:
阶码的二进制位数决定浮点数的表示范围, 尾数的二进制位数表示浮点数的精度.
以32位浮点数为例,尾数域有23位, 那么浮点数以二进制表示的话精度是23位, 23位所能表示的最大数是2^(23−1)=8388607, 所以十进制的尾数部分最大数值是8388607, 也就是说尾数数值超过这个值, float将无法精确表示. 所以float最多能表示小数点后7位, 但绝对能保证的为6位, 也即float的十进制的精度为为6~7位.
64位双精度浮点数的尾数域52位, 因为2^(52−1)=4,503,599,627,370,495, 所以双精度浮点数的十进制的精度最高为16位, 绝对保证的为15位. 所以double的十进制的精度为15~16位.

原文地址:https://www.cnblogs.com/milton/p/8023800.html