高精度数值类型选型及Swift Decimal打印差异问题咨询
关于高精度数值类型的疑问解答
1. 哪种数值数据类型的精度最高?
从你的代码来看是Swift环境,这里**Decimal类型**(对应Objective-C的NSDecimalNumber)是精度最高的常用数值类型。它属于十进制浮点类型,专门为需要精确十进制小数计算的场景设计——比如金融结算、对小数精度要求严苛的业务场景。
相比之下,Float、Double、Float80这类二进制浮点类型,没法精确表示所有十进制小数,会因为二进制与十进制的转换天生存在精度丢失问题,所以高精度场景下Decimal是最优解。
2. 如何处理像20999998.00000000001这样的数字?Float80的精度不足。
Float80作为二进制浮点类型,确实没法精确表示这个数——因为二进制浮点只能精准表示分母是2的幂的分数,而0.00000000001的分母是10^11,转不成有限的二进制分数,自然会丢失精度。
正确的处理方式是用Decimal,而且必须通过字符串初始化,这样才能完整保留所有小数位:
let preciseNum = Decimal(string: "20999998.00000000001")
千万别用浮点数字面量直接赋值给Decimal,那样会先把数值转成二进制浮点(已经丢精度了),再转Decimal也救不回来。
3. 更新疑问:为什么“print”的输出表现不同?
先看你的代码示例:
print(Decimal(string: "20999998.00000000001")) // Optional(20999998.00000000001) let a: Decimal = 20999998.00000000001 print(a) // 20999998
输出不同的核心原因是精度丢失的时机不一样:
- 第一行:
Decimal(string:)是直接把字符串解析成十进制浮点值,完整保留了输入的所有精度,所以打印时会显示完整数值(因为方法返回可选型,所以带Optional包裹)。 - 第二行:
let a: Decimal = 20999998.00000000001里的字面量会先被Swift编译器当成Double处理,而Double的精度撑不住这么多小数位,转成Double时就已经变成20999998了,再赋值给Decimal自然只剩这个值,打印出来就是20999998。
说白了:字面量赋值绕了二进制浮点的弯路,丢了精度;字符串初始化直接保留了十进制精度。
4. 对于不大于20,999,999.9769且精度要求为0.00000000001的数字,应使用哪种数据类型?
毫无疑问选Swift的Decimal类型,它的精度范围完全覆盖这个数值区间,而且支持到小数点后13位左右的精度(远超你需要的11位小数要求)。
同样要记住:必须通过字符串初始化这类数值,别用浮点数字面量赋值,避免在类型转换阶段弄丢精度。比如:
let targetNum = Decimal(string: "20999999.97690000000")
内容的提问来源于stack exchange,提问作者O. Shulzhenko
相关产品推荐
相关产品推荐

