聊聊最近很火的13.11和13.8到底谁大?
在最近我是歌手的排名统计中,出现了以下这一幕:
部分网友提出质疑,说是13.11大于13.8:
那么我们肉眼去看,根据我们12年义务教育去比对,肯定是13.8
更大一些,但是这样一道简单的数学题还难倒了不少AI模型:
AI和程序的“幻觉”
文心一言:
很明显,他在回答这道数学题时出现了胡说八道的现象,后面本人又去问了其他
AI模型
,有不少AI模型是答错的,
还有一些AI在答题时出现了,时对时错的不稳定情况。
那么为什么AI模型会出现那么低级
的错误呢?
因为大模型看到这样一组数字,意识不到应该做双精度浮点运算
那么我们程序上会不会出现这种问题呢?
就拿近年面试很流行的0.1 + 0.2
它为什么不等于 0.3
?
其实都是精度
的问题,我们先来看看程序是怎么看待我们这段运算代码的:
首先,我们需要理解浮点数在计算机中的表示方式。浮点数在计算机中是以二进制形式存储的,但并非所有的十进制小数都能精确地转换为有限长度的二进制小数。像0.1
和0.2
这样的十进制小数,在二进制表示下是无限循环小数。由于计算机的内存有限,这些无限循环小数在存储时会被截断到某个精度范围内,导致精度损失。
当两个这样的近似值相加时,结果也会是一个近似的值,而不是精确的0.3
。这就是为什么在程序中,0.1 + 0.2
的结果往往是一个接近但不等于0.3
的数,如0.30000000000000004
。
破局
那么当我们遇到精度计算的问题时,该如何去解决?
- 使用整数进行运算: 如果可能的话,将问题转化为整数运算。例如,如果你在处理货币,可以将所有的金额乘以100(或1000,取决于你需要的精度),使用整数进行运算,最后再将结果转换回小数形式。
- 使用专门的库:
对于需要高精度计算的场景,可以使用像
decimal.js
、bignumber.js
或big.js
这样的库。这些库提供了高精度的十进制数运算,可以精确表示和计算小数。 - 四舍五入或取整:
在某些情况下,你可能不需要非常高的精度,这时可以使用
Math.round()
、Math.floor()
或Math.ceil()
函数对结果进行四舍五入或取整。 - 字符串处理:
对于简单的场景,如果你只是需要显示结果给用户看,可以考虑将数字转换为字符串,然后进行字符串操作来避免精度问题。例如,你可以将两个小数相加后,使用
toFixed(n)
方法将结果保留到小数点后n位,然后再转换回字符串显示。 - 理解并接受精度限制: 在某些情况下,理解并接受浮点数的精度限制可能是最实际的选择。了解你的应用场景对精度的要求,并据此设计你的算法和数据结构。
程序对于数值的计算,并非我们直观上看到的简单表面计算,而是涉及到底层的进制转换(如十进制与二进制之间的转换)、精确的或由于精度限制而近似的二进制运算,以及可能的结果转换过程。
转载自:https://juejin.cn/post/7394993393124999168