欢迎光临散文网 会员登陆 & 注册

单精度浮点数应用时的最大存储整数

2023-06-19 11:49 作者:莫末陌寞  | 我要投稿

如果搜“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)

%E6%B1%82%E5%80%BC%E5%85%AC%E5%BC%8F%20%3D%20(-1)%5ES%20*%202%5EE%20*%20(b_0%2Bb_1%2B%E2%80%A6b_%7B22%7D)

(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提供的。

单精度浮点数应用时的最大存储整数的评论 (共 条)

分享到微博请遵守国家法律