Десятичное число во входных данных JSON в Python 3 Лямбда-функция - PullRequest
0 голосов
/ 11 мая 2018

Рассмотрим следующий вход в финансовом приложении, где важна точность:

{ "value": 3.8 }

И следующая лямбда-функция AWS:

from decimal import Decimal

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

Выход: 3.79999999999999982236431605997495353221893310546875 потому что Python проанализировал число в JSON в число с плавающей точкой, которое не может точно хранить 3.8.

Я знаю, что могу сериализовать event обратно в строку и затем дать парсеру команду использовать десятичную (это из 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 плавал?

1 Ответ

0 голосов
/ 11 мая 2018

Обновление: В вашем текущем решении нет ничего плохого.

Нет float до str до decimal.Decimal туда-обратно.

Как объясняют документы (мой акцент):

parse_float , если он указан, будет вызываться со строкой каждого JSONплавающий для расшифровки.По умолчанию это эквивалентно float (num_str).Это можно использовать для использования другого типа данных или анализатора для чисел с плавающей запятой JSON (например, decimal.Decimal).


Первоначальный ответ ниже

Передача значения float в decimal.Decimal не гарантирует требуемой точности.Это связано с тем, что по своей природе float хранится не в виде десятичного числа, а в двоичном виде.

Это может быть облегчено, если вы можете передавать строковые входные данные в 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 в виде строк вместо плавающих.

Будьте осторожны, реализация, как показано ниже, может работать , но зависит от str выполнение определенной работы, то есть правильное округление float для десятичного представления.

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

lambda_handler({"value": 3.8})  # 3.8
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...