十进制转二进制的计算
1. 整数部分
按二进制数的定义, 将十进制转为二进制实际上就是将十进制拆分为用2的级数表示的序列, 计算方法实际上就是在模拟程序的处理方式: 将二进制不断地">" (shift right, 右移), 舍掉小数部分, 记下每次个位的值, 就能得到二进制的序列. 举例, 计算201的二进制序列201 -> 1 //除2为100, 余1100 -> 0 //除2为50, 余050 -> 0 //除2为25, 余025 -> 1 //除2为12, 余112 -> 0 //除2为6, 余06 -> 0 //除2为3, 余03 -> 1 //除2为1, 余11 -> 1 //除2为0, 余1 -> 11001001 //按倒序排列即得到最终序列
2. 小数部分
计算机中记录浮点数的小数部分, 实际上也是将小数部分分解为2的级数表示的序列, 计算方法是将二进制不断地"<"(shift left, 左移), 舍掉整数部分, 记下每次个位出现的0和1, 就能得到二进制的序列. 举例, 计算0.2的二进制序列0.2 -> 0 // 乘2, 未满1, 余0.40.4 -> 0 // 乘2, 未满1, 余0.80.8 -> 1 // 乘2, 满1, 余0.60.6 -> 1 // 乘2, 满1, 余0.20.2 -> 0 // 乘2, 未满1, 余0.40.4 -> 0 // 从此进入循环0.8 -> 10.6 -> 10.2 -> 00.4 -> 0... -> 0.0011001100110011... // 按正序即得最终序列
计算机中浮点数的存储
计算机中的浮点数使用的是 IEEE 754 (IEEE二进位浮点数算术标准, IEEE Standard for Floating-Point Arithmetic), 这里有一个很形象的演示页面说明计算机是如何存储浮点数的
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位.