当前位置:首页 > 技术学院 > 技术前线
[导读]几乎所有开发者在编程学习的早期,都遇到过一个颠覆常识的诡异现象:在代码里直接计算0.1加0.2,最终得到的结果不是0.3,而是一个类似0.30000000000000004的奇怪数字。很多人把这个现象当成一个不值深究的小Bug,却不知道这背后藏着整个计算机浮点数体系的核心秘密。这套基于IEEE754标准设计的浮点数系统,用极其精巧的二进制位划分方式,在有限的存储空间里同时兼顾了极大的数值表示范围和足够的精度,同时也埋下了无数容易踩中的隐性陷阱,理解这些底层秘密,是避开所有浮点数相关疑难问题的必经之路。

几乎所有开发者在编程学习的早期,都遇到过一个颠覆常识的诡异现象:在代码里直接计算0.1加0.2,最终得到的结果不是0.3,而是一个类似0.30000000000000004的奇怪数字。很多人把这个现象当成一个不值深究的小Bug,却不知道这背后藏着整个计算机浮点数体系的核心秘密。这套基于IEEE754标准设计的浮点数系统,用极其精巧的二进制位划分方式,在有限的存储空间里同时兼顾了极大的数值表示范围和足够的精度,同时也埋下了无数容易踩中的隐性陷阱,理解这些底层秘密,是避开所有浮点数相关疑难问题的必经之路。

浮点数诞生的核心动因,是为了解决定点数的天然缺陷。如果用固定小数点位置的定点数来表示实数,要么只能表示很小范围的数值,要么就会损失大量精度,完全无法满足科学计算、工程仿真这类场景的需求。浮点数的设计思路完全跳出了固定小数点的限制,把一个实数的表示拆成三个完全独立的部分:最高位的符号位用来标识这个数是正数还是负数,中间的指数位用来标记小数点的浮动位置,剩下的尾数位用来存放这个数字的有效数字内容。这种设计就和我们日常使用的科学计数法逻辑完全一致,小数点的位置会随着指数的数值动态浮动,用很少的二进制位,就可以表示从极小的微观数值到极大的宏观数值的超宽范围,这是定点数完全不可能实现的能力。

绝大多数现代计算机都遵循的IEEE754标准,把浮点数的存储规则完全标准化,单精度32位浮点数和双精度64位浮点数是最常用的两类实现。单精度浮点数用1位存放符号,8位存放指数,剩下23位存放尾数,整体可以覆盖非常大的数值范围;而双精度浮点数用1位符号、11位指数、52位尾数来存储,有效数字的精度和可表示的数值范围都得到了大幅提升。绝大多数编程语言默认的双精度浮点数,就是用这套64位的IEEE754标准实现的。为了最大化有效数字的利用率,标准里还做了一个极其巧妙的设计:规格化的浮点数尾数的最高位永远固定是1,这个1不需要占用存储空间,直接隐藏起来,这样尾数部分的实际有效位数就比分配的存储空间多了一位,在不增加内存占用的前提下,直接提升了一位有效数字的精度。

0.1加0.2不等于0.3的经典现象,根源就在于绝大多数十进制小数,根本无法转换成有限长度的二进制小数。十进制的0.1转换成二进制之后,是一个无限循环的小数,计算机的存储空间是有限的,不可能完整存储无限长的数字,硬件只能把无限循环的二进制小数截断,用最接近的有限位数值来近似表示它。这个近似值和真实的十进制0.1之间存在极其微小的误差,同样0.2的存储值也存在微小的误差,两个带误差的数值相加之后,误差被累积放大,最终得到的结果就和真实的0.3之间出现了可以观测到的偏差。这个误差不是代码写错了,也不是CPU硬件出了问题,是浮点数二进制表示的天然属性导致的必然结果。

浮点数体系里还定义了很多特殊的非数值状态,用来处理运算过程中的边界异常情况。当运算结果的数值超出浮点数可以表示的最大值时,就会得到正无穷或者负无穷的特殊值;当出现0除以0这类完全没有数学意义的运算时,就会得到NaN非数值状态。NaN还有一个特殊的属性:它和任何数值做比较运算的结果都是假,哪怕是自己和自己比较,返回的结果也是不相等的。很多开发者在代码里遇到浮点数比较的诡异问题,根源就是没有提前判断运算结果是不是NaN。

日常开发中,很多开发者踩中浮点数的精度陷阱,本质上是用整数的逻辑来对待浮点数。浮点数绝对不能直接用等于运算符来判断两个数值是否相等,正确的做法是判断两个数的差值的绝对值,是否小于一个预先定义好的极小阈值,只要差值在这个极小的误差范围内,就认为两个数值是相等的。在金融货币这类对精度有绝对要求的场景下,绝对不能直接用浮点数来存储金额,正确的做法是把金额统一转换成以分为单位的整数,用整数类型来存储和运算,从根源上避免浮点数的精度误差。如果确实需要高精度的小数运算,就必须使用编程语言提供的专用高精度十进制运算库,而不是直接使用原生浮点数。

浮点数从来不是一个简单的基础数据类型,它是计算机科学家在存储空间、表示范围和精度之间做出的精妙权衡,理解它藏在二进制位里的所有秘密,你才能彻底避开所有浮点数相关的隐性陷阱,写出稳定可靠的数值处理代码。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭