如果您希望在加载JSON数字时保留任意精度的小数,那么必须告知json
模块使用一种能够表示此类数字的数据类型。遗憾的是,float
并不适合此用途,但decimal
和fractions
模块可以。
例如:
import json, decimal
json.loads('{"a": 10000000000022222.22}', parse_float=decimal.Decimal)
这样会得到:
{'a': Decimal('10000000000022222.22')}
使用Decimal
进行数学计算时,需要注意其与浮点数不同的特性。默认情况下,当数学运算的结果无法完全以十进制精确表达(如1/3
)时,结果将会被四舍五入到28位有效数字。然而,解析的字符串始终具有精确的精度。
# 使用30位精度
x = '1234567890.12345678901234567890'
d1 = decimal.Decimal(x)
print(d1) # d1 精确等于由 x 表示的数字
# 输出: 1234567890.12345678901234567890
d2 = d1 + 0
print(d2) # d2 已经被四舍五入至28位有效数字
# 输出: 1234567890.123456789012345679
# 如果需要更高精度
decimal.getcontext().prec = 100 # 设置上下文精度为100位
或者,如果您需要绝对不进行四舍五入的完整精度,则可以尝试使用fractions
模块。
import json, fractions
json.loads('{"a": 10000000000022222.22}', parse_float=fractions.Fraction)
这将得到:
{'a': Fraction(500000000001111111, 50)} # 注意:分数已经化简