提问人:Nico Schlömer 提问时间:6/5/2018 最后编辑:Jean-François FabreNico Schlömer 更新时间:6/2/2022 访问量:1636
用科学记数法编写 JSON 浮点
write json float in scientific notation
问:
我想使用 Python 3.6+ 以科学记数法表示 JSON 文件中的浮点数。都不是
import json
a = 0.001234567
print(json.dumps(a))
json.encoder.FLOAT_REPR = lambda x: "{:e}".format(x)
print(json.dumps(a))
json.encoder.c_make_encoder = None
json.encoder.FLOAT_REPR = lambda x: "{:e}".format(x)
print(json.dumps(a))
工作:三者皆给print
0.001234567
而不是想要的
1.234567e-03
(请注意,最后一个版本至少在 Python 2.7.15rc1 中有效。
答案也应该适用于 s 列表。float
有什么提示吗?
答:
3赞
PaulMcG
6/5/2018
#1
您必须为字典、列表、集合等添加一些特殊的大小写,但通过引用 中的抽象基类,可以避免显式测试特定类型。collections.abc
请注意,测试必须避免类型匹配,因为迭代 a 会给出一堆 1 字符的 s,它们也是可迭代的 s,依此类推,直到达到递归限制。我找不到表示“序列容器,但不是 str”的 ABC。Sequence
str
str
str
Sequence
(我还必须回应 Alex Martelli 在相关文章中的批评,即必须做这么多工作来格式化特定类型,这说明了本模块中类设计中的问题。
import json
from collections.abc import Mapping, Sequence
a = 0.001234567
class ScientificNotationEncoder(json.JSONEncoder):
def iterencode(self, o, _one_shot=False):
if isinstance(o, float):
return "{:e}".format(o)
elif isinstance(o, Mapping):
return "{{{}}}".format(', '.join('"{}" : {}'.format(str(ok), self.iterencode(ov))
for ok, ov in o.items()))
elif isinstance(o, Sequence) and not isinstance(o, str):
return "[{}]".format(', '.join(map(self.iterencode, o)))
return ', '.join(super().iterencode(o, _one_shot))
aout = json.dumps([a, a, "xyzzy", 42, {'z': a}, (a, a, a),],
cls=ScientificNotationEncoder)
print(aout)
# loading back in seems to still work okay!
print(json.loads(aout))
指纹:
[1.234567e-03, 1.234567e-03, "xyzzy", 42, {"z" : 1.234567e-03}, [1.234567e-03, 1.234567e-03, 1.234567e-03]]
[0.001234567, 0.001234567, 'xyzzy', 42, {'z': 0.001234567}, [0.001234567, 0.001234567, 0.001234567]]
评论
0赞
Nico Schlömer
6/5/2018
谢谢你的回答。这仅在转换单个浮点数时有效。放进去就行不通了。[a, a]
0赞
Nico Schlömer
6/5/2018
现在不为口述工作。如果必须将所有案件单独列出,这可能是一场艰苦的战斗。{"key": 0.00123}
0赞
PaulMcG
6/5/2018
如果您可以使用抽象类型,也许不会那么可怕collections.abc
0赞
cs95
6/6/2018
元宇宙上关于您重新开放的讨论:meta.stackoverflow.com/q/369085/4909087
1赞
Jean-François Fabre
6/6/2018
这个答案的这个代码看起来比 stackoverflow.com/a/1733105/6451573 略好,这应该是这个问题的原始问题。我认为如果它张贴在那里,并有更多的解释会更有意义。
0赞
Nico Schlömer
6/2/2022
#2
最终,我创建了自己的 json 库,可以格式化浮点数 fjson。安装方式
pip install fjson
并用作
import math
import fjson
data = {"a": 1, "b": math.pi}
string = fjson.dumps(data, float_format=".6e", indent=2, separators=(", ", ": "))
print(string)
{
"a": 1,
"b": 3.141593e+00
}
评论