Python加载JSON时19位浮点数被截断的技术咨询
问题本质:双精度浮点数的精度限制
你遇到的问题核心原因是Python的float类型是双精度64位浮点数,它的尾数仅52位,最多只能精确表示15-17位十进制有效数字。超过这个范围的十进制数无法被float精确存储,会出现精度丢失或显示形式变化的情况。
对应测试案例的细节分析
18位字符(有效数字16位)
100000000000222.22的有效数字是16位,刚好在双精度浮点数的精确表示范围内,所以json解析后能完整保留原数:>>> b = json.loads('{"a": 100000000000222.22}') >>> b {'a': 100000000000222.22}19位字符(有效数字17位)
1000000000002222.22的有效数字是17位,已触及双精度浮点数的精度上限。这个数无法被float精确存储,存储时会丢失最后一位小数的精度,因此显示为1000000000002222.2。你期望的科学计数法1.0000000000022222e+15和实际存储的float值等价,但受精度限制,实际值已和原输入存在微小差异。20位字符(有效数字18位)
10000000000022222.22的有效数字是18位,远超双精度范围,Python自动切换为科学计数法显示——这是合理的,因为常规十进制小数形式无法准确表示这个float值。
解决办法:用Decimal类型保留精确精度
如果需要精确处理这类高精度小数,不要用float,改用Python标准库的decimal.Decimal类型。通过指定json.loads的parse_float参数,让json解析器直接将数字解析为Decimal:
import json from decimal import Decimal def load_json_with_decimal(json_str): return json.loads(json_str, parse_float=Decimal) # 测试19位的情况 b = load_json_with_decimal('{"a": 1000000000002222.22}') print(b) # 输出: {'a': Decimal('1000000000002222.22')} # 若需要科学计数法显示 print(f"{'a': {b['a'].normalize():e}}") # 输出: a: 1.0000000000022222e+15
这样就能完全保留原输入的小数精度,满足你的期望。
内容的提问来源于stack exchange,提问作者Aldo Pellini
相关产品推荐
相关产品推荐

