Python 3 Lambda函数的输入JSON中的十进制 [英] Decimal in input JSON to Python 3 Lambda Function

查看:144
本文介绍了Python 3 Lambda函数的输入JSON中的十进制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请在财务应用中考虑以下输入,其中精度至关重要:

Consider the following input in a financial application, where precision matters:

{ "value": 3.8 }

以及以下AWS Lambda函数:

And the following AWS Lambda function:

from decimal import Decimal

def lambda_handler(event, context):
    value = event['value']
    print(Decimal(value))

输出为:3.79999999999999982236431605997495353221893310546875,因为Python将JSON中的数字解析为一个float,无法精确存储3.8.

The output is: 3.79999999999999982236431605997495353221893310546875 because Python parsed the number in the JSON into a float, which can't precisely store 3.8.

我知道我可以将event序列化回字符串,然后指示解析器使用Decimal(这是从

I know that I can serialize event back to a string and then instruct the parser to use Decimal (this is from the DynamoDB Python docs):

import json
def lambda_handler(event, context):
    parsed = json.loads(json.dumps(event), parse_float=Decimal)
    print(Decimal(parsed['value']))

但是那感觉就像是在被黑客入侵.首先有什么方法可以控制反序列化,以便event希望使用Decimal进行浮点运算?

But that feels like a hack. Is there some way to control the deserialization in the first place so that event prefers Decimal to float?

推荐答案

更新:您当前的解决方案没有问题.

Update: There is nothing wrong with your current solution.

没有floatstrdecimal.Decimal往返.

文档解释(我的重点):

As the docs explain (my emphasis):

如果指定了

parse_float ,则会使用要解码的每个JSON浮点的字符串来调用.默认情况下,这等效于 float(num_str).这可以用于将另一个数据类型或解析器用于 JSON浮动(例如 decimal.Decimal ).

parse_float, if specified, will be called with the string of every JSON float to be decoded. By default, this is equivalent to float(num_str). This can be used to use another datatype or parser for JSON floats (e.g. decimal.Decimal).


下面的初始答案

float值传递给decimal.Decimal并不能确保所需的精度.这是因为float本质上不是以小数形式存储,而是以二进制形式存储.

Passing a float value to decimal.Decimal does not ensure the precision you require. This is because, by its nature, float is not stored as a decimal but in binary.

如果您能够将字符串输入传递到decimal.Decimal,则可以缓解这种情况:

This can be alleviated if you are able to pass string inputs into decimal.Decimal:

from decimal import Decimal

res1 = Decimal(3.8)*Decimal(10)
res2 = Decimal('3.8')*Decimal('10')

print(res1)  # 37.99999999999999822364316060
print(res2)  # 38.0

因此,一种解决方案是确保您以字符串而不是浮点数的形式存储/读取JSON数字数据.

So one solution would be to ensure you store / read in JSON numeric data as strings instead of floats.

请注意,以下实现可能可行,但 依赖str来完成特定工作,即正确地将float舍入为十进制表示形式.

Be careful, an implementation as below may work but relies on str doing a particular job, i.e. rounding a float correctly for decimal representation.

def lambda_handler(event):
    value = event['value']
    print(Decimal(str(value)))

lambda_handler({"value": 3.8})  # 3.8

这篇关于Python 3 Lambda函数的输入JSON中的十进制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆