我正在python中编写一个下载REST数据的测试工具,通过json.loads()返回返回值,然后将DB返回的值与预期值进行比较。不幸的是,尝试打印出该值或比较该值失败。尽管JSON / Rest数据的漂亮打印是正确的并且具有完整的价值。所以像下面的例子一样简单,打印精度较低
示例:
print 1.414213562373095
1.41421356237
请注意精度降低。运行相同的比较也不起作用。在这两种情况下,我都将值强制转换为字符串,因为比较两个数字(例如1.13337和1.133333333333337)的比较是相同的数字。虽然技术上正确,但我们希望确保DB的输出符合承诺的精度。我会很感激任何解决方案。提前谢谢。
答案 0 :(得分:2)
首先,你实际上并没有失去你认为自己在你的榜样中的精确度。 print
只是比你在Python 2上预期的更严重地截断。比较应该在这个数字上正常工作,只要你不会在其他地方失去更多精度。
如果您有实际的精度限制问题 - 例如,带有20位数字的JSON - 您可以解决这个问题。 json.loads
默认将数字解析为float
s,浮点数的精度有限。如果您不想这样,请更改json.loads
解析数字的方式:
>>> import json
>>> x = '{"a": 1.2345678901234567890}'
>>> json.loads(x, parse_float=str, parse_int=str, parse_constant=str)
{u'a': '1.2345678901234567890'}
>>> from decimal import Decimal
>>> json.loads(x, parse_float=Decimal, parse_int=Decimal, parse_constant=Decimal)
{u'a': Decimal('1.2345678901234567890')}
答案 1 :(得分:0)
我会像user2357112建议的那样做。 没有足够的信息来准确说明您与数据库进行比较的过程,但为了将来参考,您可以使用以下格式:
<div style="height: 150px; border: 1px solid red;box-sizing:border-box">
<span class="fixIssue" style="display:flex; justify-content:flex-start;flex-wrap:nowrap;height:100px; border:1px dotted green;">
<span style="flex:0 0 auto; margin-right:10px;">
<span class="imgSpan">
<img src="https://dummyimage.com/68x68/d612e8/" class="thumbnail" />
</span>
</span>
<span style="flex:0 1 auto; margin-right:10px; overflow: hidden">
<span class="textSpanInner">
<a href="" class="linkStyle">Big Name HereBig Name HereBig Name HereBig Name Here</a>
</span>
</span>
</span>
</div>
编辑:看起来Zinki打败了我。
答案 2 :(得分:0)
Python(以及许多其他编程语言)本质上存在将十进制数表示为浮点数和浮点算术(包括比较浮点数)的问题。有关原因的详细说明,请参阅这些页面:Floating Point Arithmetic: Issues and Limitations,What Every Computer Scientist Should Know About Floating Point Arithmetic。
如果在Python中需要高级别的精度,使用Decimal
类可以提供帮助。从Python文档:“十进制模块提供对快速正确舍入的十进制浮点运算的支持”。有关详细信息,请参阅Decimal fixed point and floating point arithmetic。
以下是一个示例(来自Python文档),显示了用户可更改的精度级别:
>>> from decimal import *
>>> getcontext().prec = 6
>>> Decimal(1) / Decimal(7)
Decimal('0.142857')
>>> getcontext().prec = 28
>>> Decimal(1) / Decimal(7)
Decimal('0.1428571428571428571428571429')
编辑: 根据评论中的讨论,我正在进一步研究浮点比较,如果您希望与特定精度进行比较,则可以在Python中使用math.isclose。有关详细信息,请参阅What is the best way to compare floats for almost-equality in Python?。 有关浮点比较的分析,请参阅:Comparing Floating Point Numbers
答案 3 :(得分:0)
这是完整的编码答案,可以正确打印任意大的十进制数。不幸的是,您必须使用DecimalEncoder类将值作为字符串返回。当我独自运行这个代码时,我得到了我想要的东西。 (记住这是用于测试,我想确保python不会以某种方式改变值)。因此,当我从数据库中获取值时,我可以正确地比较值,而无需python舍入或剪切值。
在我的测试环境中,由于某种原因,此解决方案将最后一位数字舍入但不再剪切为11位精度。交换json.loads调用将显示原始问题。
不幸的是,这会将数据类型更改为字符串,我仍然需要弄清楚为什么我的代码将比较值进行舍入,但我可以在周末看出来:)。谢谢大家的帮助!!
import json
import decimal # use decimal to tell python to leave my numbers alone
class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
return str(o)
return super(DecimalEncoder, self).default(o)
class JSONUtils:
def __init__( self, response ):
self.response = response
self.jsonData = None
self.LoadData( )
print 'jsonData: ' + json.dumps( self.jsonData, cls=DecimalEncoder, indent=2 )
def LoadData ( self ):
if ( self.jsonData == None ):
if ( type( self.response ) == str or type( self.response ) == unicode ):
# self.jsonData = json.loads(self.response )
self.jsonData = json.loads(self.response, parse_float=decimal.Decimal )
def GetJSONChunk( self, path ):
returnValue = ''
curPath = ''
try:
if ( type( path ) == str ):
returnValue = self.jsonData[path]
elif (type( path ) == list):
temp = ''
firstTime = True
for curPath in path:
if firstTime == True:
temp = self.jsonData[curPath]
firstTime = False
else:
temp = temp[curPath]
returnValue = temp
else:
print 'Unknown type in GetJSONChunk: ' + unicode( type( path ))
except KeyError as err:
ti.DBG_OUT( 'JSON chunk doesn\'t have value: ' + unicode( path ))
returnValue = self.kNoNode
except IndexError as err:
ti.DBG_OUT( 'Index does not exist: ' + unicode( curPath ))
returnValue = self.kInvalidIndex
return returnValue
myJSON = JSONUtils( '{ "fldName":4.9497474683058327445566778899001122334455667788990011 }' )
value = str( myJSON.GetJSONChunk ( 'fldName' ))
print str( type( value ))
print value
输出:
<type 'str'>
4.9497474683058327445566778899001122334455667788990011