4-浮点数

本文详细解析了实数在计算机中的二进制科学计数法表示,包括浮点数的转换、IEEE754标准、定点数与浮点数的存储机制,以及浮点数的表示范围、精度损失和BigDecimal作为替代方案。重点介绍了有效数字域、指数域的处理和浮点数的精确表示问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习王争专栏浮点数总结

目录

1,实数的二进制科学计数法

1)实数的概念

2)十进制的科学计算数

3)二进制的科学计数法

3-1)浮点数转换为二进制

二,实数二进制的存储:定点数

三,实数二进制的存储:浮点数

1)浮点数的公式:二进制科学计数法

2)浮点数公式详解。

2-1)符号位S

2-2)有效数字域M

2-3)指数域E

指数域值为0时:用来辅助表示浮点数0

指数域值为255时,用来表示无穷大或无效数NaN

四,浮点数的表示范围和精度

1)浮点数的表示范围

2)浮点数的精度(重)

3)浮点数整数能准确表示的整数范围以及最小正数(重)

五,浮点数的替代品:BigDecimal

1)为何使用BigDecimal

2)使用注意事项

六,double双精度的


1,实数的二进制科学计数法

1)实数的概念

实数是一种概念,可以理解为小数。整数也可以看作是实数比如5,可以看作是5.0。

而在java中实数可以理解为float,double两种浮点数。

整数在计算机中是以补码的方式存储的,而实数在计算机中是以一种科学计算法进行存储的。

2)十进制的科学计算数

对于十进制的科学计算法,使用excel的应该都有过一串长数变成 1.23E6。这就是简化后的科学计数法。

正常如12300000000 科学计数法为 1.23* 10^10。而再省略则可以变成xEy这样的模式,即E代表10,而y表示指数。如上可以缩减为1.23E10。

3)二进制的科学计数法

首先二进制的科学计数法已经有一套规范文件:IEEE754标准。绝大多数计算机是以此为基础存储浮点数。

3-1)浮点数转换为二进制

假设对于一个小数如12.375,要将其转换为二进制,可以考虑将其整数和小数分别转换为二进制,再以'.'进行串联,最后转换成 1100.011这样的模式,而负数-12.375,则为-1100.011。

对于整数部份的转换比较简单,上一章也有写,主要写下小数部份使用的乘2取整数。

此方法王争的我没看明白,以知乎上看到的为例。

我们对十进制计算小数的时候,小数后的每一位都对应一个权值,1/10, 1/10^2, 1/10^3。

那么同理,二进制的小数后面的值也有对应的权值, 1/2, 1/2^2, 1/2^3.

那么以0.375为例,

先以0.375/(1/2),不够,那么此位为0

再以0.375/(1/2^2),够,此位为1,剩下0.125

再以0.125/(1/2^3),够且刚好相等,此位为1,结果

得到011,与整数一串联就是 1100.011.

但是此时上面的都是除,和乘2取整法无关,可以转换为(假设floor函数为计算当前位是否够的,即是否大于1的):小数点后第一位:floor(0.375/(1/2)) = floor(0.375/0.5) = floor(0.375 * 2) = floor(0.75) 小于1,此位为0

小数点后第二位:floor(0.75 /(1/2)) = floor(0.75 * 2) = floor(1.5) 够1,去掉1,剩下0.5. 为什么此处只/1/2,而不是/1/2^2,是因为第一步取的没有取出来

.....

再加上看的方便,可以直接取整。

另注意点:

上面的是可以除尽或乘尽的,但是有些是没有办法除尽的或除尽的,比如0.1

其小数点后的二进制为 00001 0001 0001,无限循环,这也是浮点数会精度缺失的原因。

二,实数二进制的存储:定点数

上面的存储方式,计算机还是没法看懂,可以用如下的定点数方式存储(点号是固定的)

第一位决定正负,然后固定的位数存储整数,固定的位数存取小数

但该方式还有个问题:

1,会浪费很多的存储空间,假如都是整数或小数

2,取值范围会很窄。比如整数部份是20位,那么最大的整数就是2^20。同样的4字节,比int范围小很多

三,实数二进制的存储:浮点数

为了有效利用空间,于是发明了浮点数,即点号在二进制中不固定的。

对应到java的就是float和double.

1)浮点数的公式:二进制科学计数法

公式:(-1)^S*M*2^E

其中S是符号位,0表示正数,1表示负数, M表示的是有效数字域,E表示的是指数域。

例如上面的12.375 可以表示为(-1)^0 * 1.100011*2^3。 其中S为0,

E为3 其二进制为 1000 0010 并不是0000 0011(具体的下面讲),

M为100011 完全体float的E是 1000 1100 0000 0000 0000 000 (前面是少了个1,具体的下面讲解)

2)浮点数公式详解。

都在float进行说明。

2-1)符号位S

对于S比较好理解,同整数一样的,用于表示符号位,根据公式,当为0时,刚好-1^0 为0,且示正,1时为-1,表示负数。

2-2)有效数字域M

有效数字域M。

因IEEE754规定,其整数必须为1,因此整数位可以不需要存储,只存储小数即可,整数位默认为1。

因此对于23位有效数字域的单点数浮点数float,实即有24位有效数字。

整数默认为1了,此时没法表示0了,此时使用指数域来表示,当E为0时,IEEE754规范要求,从有效数字域读取的二进制位不需要在前面添加1.

2-3)指数域E

指数域没有使用原码或补码来存储,float的指数域的范围是[-126, 127]。这里需要说明一下,指数域没有使用原码与反码,也就没有符号位这一说。 指数域是8位,实际范围是0-255 (0000 0000 -- 1111 1111)。但是0-255没有办法表示负数,因此存储的时候都需要对值进行+127操作,这也是上面的值为什么是1000 0010 并不是0000 0011的原因,而当使用时,就需要-127。此时还有两个值0与255不在其范围中,这两个值有特殊用处

先看一下-12.375的二进制科学法的表示。

指数域值为0时:用来辅助表示浮点数0

有效数字域M。默认整数位1,那么就无法表示0时的情况了。

那么当指域数值为0时,就不再有效数字域的二进制位前加1,即实现了整数位的默认0.

此时如果有效数字域M里的值全为0,指数域E也为0,那么就表示浮点数0了。

指数域值为255时,用来表示无穷大或无效数NaN

当指数域值为255时,如果M有效数字域里的值全为0,那么当S为0时表示正无穷大,S值为1时,表示负无穷大。

如果M的数字域里的值不为0,那么表示无效数NaN。

Java jdk里Float里的,可以用来表示正无穷和负无穷以及无效数Nan

public static final float POSITIVE_INFINITY = 1.0f / 0.0f;

public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;

public static final float NaN = 0.0f / 0.0f;

四,浮点数的表示范围和精度

1)浮点数的表示范围

浮点数有效位最大情况下为23位全是1,加上整数的1。为1.11111

而指数位的范围为-126-127.

那么最大值为1.111....1111*2^127

最小值为-1.1111.111*2^127

比同为4字节的int大的多,比long都大

但是牺牲了精度,很可能会有不同的整数最终存为float的是一样的。

根据鸽笼原理,32个bit,最多存储2^32个实数,表达范围大了,必然有重复的。

2)浮点数的精度(重)

浮点数的有效位是24位,那么如果要表达的数的个数超过了24位,那么就就会做出取舍(不是直接截取,特有的四舍五入)。就会导致精度丢失。

3)浮点数整数能准确表示的整数范围以及最小正数(重)

1,整数范围

因为有效位是24位,无符号位,那么最多能表示的数据为2^24个,范围则为0-2^24-1,负数则为 -2^24+1 - 0。所以完整的范围为 -2^24 + 1 ~~ 2^24 - 1。

后续的则是在此基础上*2,除2,或者根据浮点数的截取方式定。

如果截图完整一段,那么对于2的整数倍的数是可以准确表示的,但现在并不确定是怎么截取(没有深入研究了)。

2,最小正数

E的取值范围为-126-127,要最小取-126

M最小的值为1.000,即23位上全是0

因此最小正数为1*2^-126。

五,浮点数的替代品:BigDecimal

1)为何使用BigDecimal

浮点数容易精度丢失,而BigDecimal不会。在BigDecimal中整数位与小数位是分开计算的。

2)使用注意事项

不能传入float来构造,因为在float传入时精度就丢失了,需要传入的是字符串。

六,double双精度的

暂时理解为,除了范围变大了,内核是一样的。只是能精准表示出来的值更多了。

粗略算了下,E的域为0 ~ 2047 (无符号位)

那么有效范围为-1022 ~ 1023。float是加127,double为1023.

float的0对应double的0

float的255对应double的2047.

双精度double有效位M为52+1的有效位,精度大很多。

而指数域

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值