首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用标准json模块格式化浮点数

使用标准json模块格式化浮点数
EN

Stack Overflow用户
提问于 2009-09-19 00:08:38
回答 14查看 88.7K关注 0票数 117

我使用Python2.6中的标准json module来序列化浮点数列表。然而,我得到了这样的结果:

代码语言:javascript
复制
>>> import json
>>> json.dumps([23.67, 23.97, 23.87])
'[23.670000000000002, 23.969999999999999, 23.870000000000001]'

我希望浮点数的格式只有两个十进制数字。输出应如下所示:

代码语言:javascript
复制
>>> json.dumps([23.67, 23.97, 23.87])
'[23.67, 23.97, 23.87]'

我试着定义我自己的JSON编码器类:

代码语言:javascript
复制
class MyEncoder(json.JSONEncoder):
    def encode(self, obj):
        if isinstance(obj, float):
            return format(obj, '.2f')
        return json.JSONEncoder.encode(self, obj)

这适用于唯一的浮动对象:

代码语言:javascript
复制
>>> json.dumps(23.67, cls=MyEncoder)
'23.67'

但对于嵌套对象则失败:

代码语言:javascript
复制
>>> json.dumps([23.67, 23.97, 23.87])
'[23.670000000000002, 23.969999999999999, 23.870000000000001]'

我不想有外部依赖,所以我更喜欢坚持使用标准的json模块。

我如何才能做到这一点?

EN

回答 14

Stack Overflow用户

发布于 2009-11-14 11:16:28

代码语言:javascript
复制
import simplejson
    
class PrettyFloat(float):
    def __repr__(self):
        return '%.15g' % self
    
def pretty_floats(obj):
    if isinstance(obj, float):
        return PrettyFloat(obj)
    elif isinstance(obj, dict):
        return dict((k, pretty_floats(v)) for k, v in obj.items())
    elif isinstance(obj, (list, tuple)):
        return list(map(pretty_floats, obj))
    return obj
    
print(simplejson.dumps(pretty_floats([23.67, 23.97, 23.87])))

发射

代码语言:javascript
复制
[23.67, 23.97, 23.87]

没有必要使用monkeypatching。

票数 60
EN

Stack Overflow用户

发布于 2015-03-16 05:30:42

非常不幸的是,dumps不允许你对浮点数做任何事情。然而,loads做到了。因此,如果您不介意额外的CPU负载,您可以通过编码器/解码器/编码器抛出它,并获得正确的结果:

代码语言:javascript
复制
>>> json.dumps(json.loads(json.dumps([.333333333333, .432432]), parse_float=lambda x: round(float(x), 3)))
'[0.333, 0.432]'
票数 30
EN

Stack Overflow用户

发布于 2011-04-07 07:29:37

如果您使用的是Python 2.7,一个简单的解决方案就是将浮点数显式舍入到所需的精度。

代码语言:javascript
复制
>>> sys.version
'2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)]'
>>> json.dumps(1.0/3.0)
'0.3333333333333333'
>>> json.dumps(round(1.0/3.0, 2))
'0.33'

这是因为Python2.7生成了float rounding more consistent。不幸的是,这在Python 2.6中不起作用:

代码语言:javascript
复制
>>> sys.version
'2.6.6 (r266:84292, Dec 27 2010, 00:02:40) \n[GCC 4.4.5]'
>>> json.dumps(round(1.0/3.0, 2))
'0.33000000000000002'

上面提到的解决方案是2.6的变通方法,但没有一个是完全足够的。如果您的Python运行时使用C版本的json.encoder.FLOAT_REPR模块,则Monkey JSON不起作用。Tom Wuttke答案中的PrettyFloat类可以工作,但前提是%g编码对您的应用程序全局有效。%.15g有点神奇,它之所以有效,是因为浮点精度是17位有效数字,并且%g不打印尾随零。

我花了一些时间尝试制作一个PrettyFloat,允许自定义每个数字的精度。例如,语法类似于

代码语言:javascript
复制
>>> json.dumps(PrettyFloat(1.0 / 3.0, 4))
'0.3333'

要做到这一点并不容易。从float继承是很笨拙的。从Object继承并使用带有自己的JSONEncoder ()方法的default子类应该是可行的,除了json模块似乎假定所有自定义类型都应该序列化为字符串。即:在输出中最终得到Javascript字符串" 0.33“,而不是数字0.33。也许有一种方法可以让它工作,但它比看起来更难。

票数 29
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1447287

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档