什么是浮点数?
浮点数是相对定点数而言的,我们先把这两个概念搞清楚。
定点数和浮点数都是用于表示数值的格式,它们的主要区别在于如何表示小数部分,也就是如何处理小数点的问题。
定点数是将一个数的整数部分和小数部分用固定的位数来表示,小数点的位置是固定的。这里的"定点"是指小数点的位置是固定不变的,注意不是说这个数一定要有小数部分。例如:我们有一个四位的定点数1234,约定前两位表示整数部分,后两位表示小数部分,那么这个数就代表12.34。
浮点数则是一种更复杂的数值表示方法,其中小数点的位置是可以变动的。它由三部分组成:符号位、指数部分和尾数部分。以单精度浮点数为例,它占用4字节,其中1位是符号位,8位是指数部分,23位是尾数部分。例如,我们可以将数字123.45表示为1.2345乘以10的2次方,这就是一个浮点数。如果你了解过科学计数法,可以看到浮点数就是使用的科学计数法。
为什么需要浮点数?
定点数对比浮点数,表示相同数字的时候,定点数可能使用更多的存储空间。例如,在BCD编码中,1个数字需要4bit表示,这意味着32位只能表示1亿个数,再大的数字就需要更多的bit来表示。
其次,定点数无法同时表示很大的数字和很小的数字。假设我们用一个16位的定点数来表示数值,其中8位用于表示整数部分,8位用于表示小数部分。
- 此时能表示的最大数就是255.996(即二进制的11111111.11111111)。那么,如果我们需要表示一个比这个数大的数,例如300,就无法用这个16位的定点数来表示了。
- 对于较小的数字,由于小数部分只有8位,最小能表示的数是1/(2^8)=0.0039(即二进制的0.00000001)。因此,这个16位的定点数也无法表示0.0001这样的小数。
因此,浮点数应运而生,作为一种更有效的处理小数的方法。浮点数的优点是可以表示非常大或非常小的数,而且可以保持相对较高的精度,但是计算速度相对较慢。
浮点数标准
在科学计算中,我们通常使用IEEE 754标准来表示小数,这是一种浮点数表示和运算的标准,是现代计算机中处理浮点数的基础。在这个标准中:
数字它由符号位、指数位和尾数位三部分组成。符号位决定了浮点数的正负,指数位决定了浮点数的大小,尾数位则决定了浮点数的精度。
单精度浮点数可以保证6-7位十进制有效数字,取值范围是10的-38次方到10的38次方,占用4字节空间,包括符号位1位,阶码8位,尾数23位。
双精度浮点数则可以保证15-16位十进制有效数字,取值范围是10的-308次方到10的308次方,占用8字节空间,包括符号位1位,阶码11位,尾数52位。
精度损失问题
我们在上面说的有效数字为什么不是固定的7位或者16位?
这是因为计算机采用二进制系统,有些十进制小数无法被二进制精确表示,这就可能导致精度降低。比如,0.1在二进制中是一个无限循环小数,所以在计算机中,无论是单精度还是双精度,都无法精确地表示0.1,这就可能导致精度降低。
附带介绍下十进制小数转二进制的方法:不断地将小数位乘以2,如果结果小于1就取0,如果结果大于1就取1,然后再减去1,然后继续这个过程。
如果小数位是无限非0循环,我们就会因为只能记录最大有效位而导致精度丢失。而在进行加法运算时,我们需要先对齐,再计算。如果两个数的指数位相差较大,我们就需要将指数位较小的数通过有效位右移的方式进行对齐,这样就会损失一部分有效位的数据,从而导致精度损失。
精确数值方法
那么,有没有不丢失精度的方法来表示小数呢?答案是肯定的。首先,我们可以使用定点数,通过BCD编码,每个数字用4bit表示,左边x位bit表示整数,右边y位bit表示小数,比如很多开发语言中都有的decimal数据类型。另外,我们也可以使用整数类型,比如金额可以用分来表示,例如100.45元可以转换为10045分,这样就可以避免精度损失。
总结
浮点数是一种非常有效的表示小数的方法,虽然它在处理某些情况时会有精度损失的问题,但是我们可以通过适当的方式来避免这种情况的发生。作为开发人员,我们需要了解浮点数的工作原理和使用注意事项,这样才能保证程序的健壮性。
更多学习资源
我注册了一个微/信/公/众/号:萤火架构,后续会分享很多架构方面的经验和认识,欢迎关注,以免错过精彩内容。
最后用一幅图做个总结,如需高清大图请关注公众号后获取。