gpt4 book ai didi

python - 使用 Python 和 Google App Engine 问题进行 float 格式化 JSON 转储

转载 作者:太空宇宙 更新时间:2023-11-03 16:02:43 25 4
gpt4 key购买 nike

我目前正在使用 python 并在 Google App Engine 上创建一个简单的 API,该 API 允许用户通过使用命令行进行 API 调用来使用 GET、POST、DELETE 和 PUT 动词。我正在使用curl 通过API 调用来操作数据。我已经能够成功添加数据并将其显示回来,但问题是我有一个“价格”属性,并且该价格作为 float 存储在 GAE(Google App Engine)上的数据存储中,并且数字按原样格式化已提交,但当 JSON 显示数据存储中的内容时,它具有不同的格式。例如,存储价格 8.99,JSON 响应显示 8.9900000000000002。我很确定这不是 GAE 问题,而是 JSON 问题。

问题示例:

curl --data "name=t-shirt&description=Star Trek&price=8.99&user=test1" -H "Accept: application/json" https://mywebsite.appspot.com/product

正确存储在数据存储中,但返回 JSON,如下所示:

{"description": "Star Trek", "price": 8.9900000000000002, "name": "t-shirt", "user": "test1", "key": 5206065687822336}

这是我的 models.py

from google.appengine.ext import ndb

class Model(ndb.Model):
def to_dict(self):
d = super(Model, self).to_dict()
d['key'] = self.key.id()
return d

class User(Model):
username = ndb.StringProperty(required=True)
password = ndb.StringProperty(required=True)

class Product(Model):
name = ndb.StringProperty(required=True)
description = ndb.StringProperty(required=True)
price = ndb.FloatProperty()
color = ndb.StringProperty()
size = ndb.StringProperty()
user = ndb.StringProperty(required=True)

class Sales(Model):
products = ndb.KeyProperty(repeated=True)
datetime = ndb.DateTimeProperty(required=True)
quantity = ndb.IntegerProperty(repeated=True)
product_cost = ndb.FloatProperty(repeated=True)
total_cost = ndb.FloatProperty()
latitude = ndb.FloatProperty()
longitude = ndb.FloatProperty()
user = ndb.KeyProperty(required=True)


def to_dict(self):
d = super(Sales, self).to_dict()
d['products'] = [i.id() for i in d['products']]
return d

这是产品.py:

import webapp2
from google.appengine.ext import ndb
import models
import json

class Product(webapp2.RequestHandler):
#Create a Product entity
def post(self):
if 'application/json' not in self.request.accept:
self.response.status = 406
self.response.status_message = 'Not acceptable, API only supports application/json MIME type.'
return
new_product = models.Product()
name = self.request.get('name', default_value=None)
description = self.request.get('description', default_value=None)
price = self.request.get('price', default_value=0)
color = self.request.get('color', default_value=None)
size = self.request.get('size', default_value=None)
user = self.request.get('user', default_value=None)

if name:
new_product.name = name
else:
self.response.status = 400
self.response.status_message = 'Invalid request, name required'
if description:
new_product.description = description
else:
self.response.status = 400
self.response.status_message = 'Invalid request, description required'
if price:
new_product.price = float(price)
if color:
new_product.color = color
if size:
new_product.size = size
if user:
new_product.user = user
else:
self.response.status = 400
self.response.status_message = 'Invalid request, username required'
key = new_product.put()
out = new_product.to_dict()
self.response.write(json.dumps(out))
return

#Return an Product entity
def get(self, **kwargs):
if 'application/json' not in self.request.accept:
self.response.status = 406
self.response.status_message = 'Not acceptable, API only supports application/json MIME type.'
self.response.write(self.response.status_message)
return
#Return selected product details
if 'id' in kwargs:
out = ndb.Key(models.Product, int(kwargs['id'])).get().to_dict()
self.response.write(json.dumps(out))
#Return all product ids
else:
q = models.Product.query()
keys = q.fetch(keys_only=False)
results = {x.key.id() : x.to_dict() for x in keys}
self.response.write(json.dumps(results))

我为我的过分道歉,但我想确保一切都可以看到。任何帮助将非常感激。我已经看过一些类似的项目,但我在这里使用字典的方式似乎无法正确获取此格式。

提前谢谢您!

最佳答案

我认为这实际上不是一个问题。如果您想了解为什么会出现这种差异,您可能需要阅读有关 floating point numbers 的维基百科文章。 TLDR 是,0 到 1 之间已经有无限多个有理数,但计算机只能存储有限数量的数据。更重要的是,您通常希望存储 32(单)或 64(双)位数据内的实数,以实现高效计算。因此,机器编号只是实数的子集,您通常必须四舍五入到最接近的机器编号。如果点始终位于同一位置并且您使用的是基数 10 数字,那么这不会成为问题,因此您会知道舍入“8.99”时不会出现错误,但对于 中定义的普通 float 而言,情况并非如此IEEE 754。

基本上 8.99 = 8.9900000000000002 在这里成立。

您有多种解决问题的选择:

1) 不要解决问题,只是对显示的值进行四舍五入

警告:这可能不是您想要的。
通常,可以对显示时的错误进行四舍五入,因为通常错误非常小,例如在游戏中,这可能是可以接受的。然而,在这种情况下,您似乎正在创建一家商店,如果不同地方有不同的舍入,则可能会出现问题。例如,在某些情况下,它可能会在订单上产生 0.01 的差异,这可能会导致各种问题。不要以 float 存储价格/金额。

2)使用整数值[可能是最好的选择]

您不是将 8.99 存储为数据库中的整数,而是将 899 存储为整数。如果仅使用加法/减法,整数算术不会出现舍入问题。

这可能有点不方便,因为它将涉及更新数据库和显示数字(即您必须在正确的位置插入一个点)。但这可能是您最安全的选择,如果您无法访问专门的号码,这通常被认为是一个不错的选择。

3) 使用具有正确基数的定点数

如果您对这些数字进行大量算术运算,那么使用定点数字库可能会更方便,并且基本上使用针对您的问题量身定制的有理数表示形式。它与选项 2 基本相同,但您不必自己实现所有内容,并且具有更大的灵 active 。不过,我个人会选择选项 2,因为我不知道是否有这样一个库可以在 Python 和 Javascript 中使用,而且它可能只涉及对项目的不必要的依赖。

关于python - 使用 Python 和 Google App Engine 问题进行 float 格式化 JSON 转储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40173295/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com