Decimal in input JSON to Python 3 Lambda Function

家住魔仙堡 提交于 2020-05-15 02:40:25

问题


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

{ "value": 3.8 }

And the following AWS Lambda function:

from decimal import Decimal

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

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

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']))

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?


回答1:


Update: There is nothing wrong with your current solution.

There is no float to str to decimal.Decimal round-trip.

As the docs explain (my emphasis):

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).


Initial answer below

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.

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

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

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


来源:https://stackoverflow.com/questions/50282080/decimal-in-input-json-to-python-3-lambda-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!