单精度浮点数应用时的最大存储整数
如果搜“32位单精度浮点数的最大值”一般都是 3.4 * 10^38。
Q:看着感觉能存很大的值,至少百亿千亿无所谓?还有很多位的盈余。
A:其实存个千万都费劲,因为整数部分的值丢失是难以接受的。
执行以下代码得(C# for Unity)
用unity是因为输出方法最短最简单(

以上,
赋值2^23的爆金币了,
赋值2^23-1的爆金币了,
赋值2^23+1的对了,
得2^23的乘法对了,
得2^24的乘法爆金币了。

初看 3.4 * 10^38是很难琢磨的一个值 因为它单纯是 2^128 结果的十进制转述。
广义的浮点数是小数点任意位置的,即 10可以表示为:10^1 * 1、也可以为10^2 * 0.1。
被float、double等定义的浮点数是IEEE提供的一个大家遵循的表示标准,这里的位分配即是IEEE对float提供的标准。
32位的浮点数的位分配:1个符号(S),8个阶码(E),23个尾数(bn)
(1) 符号
0正数,1负数没什么好说的。
(2) 阶码
① E ∈ [-126,127]
Q:E为什么属于这个区间?
A:上文提及,浮点数中为阶码(指数)提供了八位
在IEEE标准中,E要+127 即 + 0111 111,[-126,127] + 127之后为[1,254]。
对应到二进制是[0000 0001, 1111 1110],然后0和255保留用来做其他的事情。
② 我在写文的时候还看有:
Q:为什么float的最大值不是6.8x10^38(2^129)而是3.4x10^38(2^128)。
A:转为二的指数就明确一些了,float存不住2^128,到E=128就爆了,即阶码1111 1111,
上文已经说过255被保留有特殊含义(表示无穷),尾数能提供一个最大不超过2的值,
2^127 x 2 = 2^128。
(3) 尾数
上文提到,尾数最大不超过2。
那么再想一下数学上的科学计数法,一个数也会被归正为10^n * z.zzz(Z∈[0,9]正整数),这样的一个数。例如123.456 = 10^2 * 1.23456。
对尾数的处理就像这样。
规格化:
计算机中对数的处理都是二进制的,首先要把十进制数转为二进制数。
本篇幅以0.0625为例子。
① 十进制转二进制 (0.0625)10 = (0 点 0001)2
点:这个点是浮点的表达。
当0.x时,点在第二位之前,当为2.x时(10 点 0000) = 点就在第三位之前了。
小数部分计算二进制:
值不断检测去商余2^n(n<0)。
例如在本例: 0.0625 / 0.5(2^-1) = 0……0.0625,和整数部分的运算逻辑是相同的。
② 规格化处理:
就像二进制的科学计数法:0 .0001 = 2^-4 * 1.000
补到去除1.000的1,然后对.000 补0到23位。
最后0.0625的编码为0 (127-4)10 0*23。
在上文的规格化处理时,直接去了二进制科学计数法之后的点前值1,因为它必然是1。
对于一个非0的数,二进制科学计数法就是去找它从左到右的第一个1。
对于0,浮点数使用 阶码和尾数 全为0表示。
既然是必然的,那就没有必要存储。
整数值丢失:规格化处理就是整数值丢失的地方。
很好解释,你有100位的1,最后也只能存24位1(包括上文说的丢弃的1和23位1)。
存入的时候丢弃1,读取的时候按阶码补0,数据自然就丢失了。
最后可能有小迷糊疑惑32位的数怎么整的大于32的位数,这个位置是CPU提供的。