python为什么以及如何截断数字数据?
我在这里处理两个变量,但很困惑,因为当我想将它们作为URL参数发送时,它们的值似乎在改变(它们失去了精度) 当我在这里从python解释器复制它时,看看这个场景:python为什么以及如何截断数字数据?,python,serialization,floating-accuracy,Python,Serialization,Floating Accuracy,我在这里处理两个变量,但很困惑,因为当我想将它们作为URL参数发送时,它们的值似乎在改变(它们失去了精度) 当我在这里从python解释器复制它时,看看这个场景: >>> lat = 0.33245794180134 >>> long = 32.57355093956 >>> lat 0.33245794180133997 >>> long 32.57355093956 >>> nl = str(lat)
>>> lat = 0.33245794180134
>>> long = 32.57355093956
>>> lat
0.33245794180133997
>>> long
32.57355093956
>>> nl = str(lat)
>>> nl '0.332457941801'
>>> nlo = str(long)
>>> nlo '32.5735509396'
那么发生了什么?当我将lat
和long
序列化为字符串并将它们作为url查询字符串的一部分发送时,如何确保不会丢失它们的精确性
为澄清情况:
因此,我需要的是以最小的精度/信息损失将浮点转换为字符串的最佳方法。您可以尝试使用字符串格式来获得所需的精度
>>> lat = 0.33245794180134
>>> lat
0.33245794180134
>>> "%.14f" % lat
'0.33245794180134'
>>>
编辑以合并评论:
>>> '{0:.14f}'.format(lat)
'0.33245794180134'
>>>
str
用于人类可读的表示。它很少产生与产生提供给它的值的表达式等价或相似的内容<另一方面,code>repr则明确表示了这一点。事实上,它是REPL用来反馈表达式结果的
请注意,尽管浮点仍然是有限精度的,并且不能准确地表示某些数字,无论您如何将它们序列化为字符串。通常,如果您使用
'%.14f'%lat
,您将失去精度
要从浮点中获得完全精度,请使用repr()
例如:
>>> lat = 1/3.
>>> lat
0.3333333333333333
>>> str(lat).count('3')
12
>>> ('%.14f' % lat).count('3')
14
>>> repr(lat).count('3')
16
>>>
顺便说一句,您正在使用一个旧的Python
>>> 0.33245794180134 == 0.33245794180133997
True
>>>
Pythons 2.7之前的版本通过使用17位有效的十进制数字生成repr(a_float)
,因为这将保证float(repr(a_float))==a_float
。新方法是使用提供相同保证的最小位数。按Ctrl-F键搜索repr()
如果您是从外部源获取这些数字,那么您可能会因为将它们浮点化,然后使用14位小数精度对它们进行序列化而丢失精度
>>> lat = 0.33245794180134
>>> lat
0.33245794180134
>>> "%.14f" % lat
'0.33245794180134'
>>>
如果你是通过计算得到这些数字的,那么你可能会因为用14位小数的精度对它们进行序列化而失去精度
>>> lat = 0.33245794180134
>>> lat
0.33245794180134
>>> "%.14f" % lat
'0.33245794180134'
>>>
摘要:一般来说,如果使用“%.14f”%lat,您将丢失精度—不是Python,不是浮点算术,而是您。Python标准库十进制模块中的十进制类型肯定是您想要的。默认情况下,它允许您保持28位精度,但不会强制将数字转换为二进制浮点表示形式。十进制类型还允许涉及其他类型的数字的数学运算,而无需转换 您的示例已转换为十进制:
>>> import decimal
>>> lat = decimal.Decimal(repr(0.33245794180134))
>>> long = decimal.Decimal(repr(32.57355093956))
>>> lat
Decimal('0.33245794180134')
>>> long
Decimal('32.57355093956')
>>> repr(lat)
'0.33245794180134'
>>> repr(long)
'32.57355093956'
将数字添加到十进制:
>>> lat + 2
Decimal('2.33245794180134')
避免数字的二进制浮点表示的不精确性,如1.1:
>>> onepointone = decimal.Decimal(repr(1.1))
>>> onepointone
Decimal('1.1')
python标准库中的decimal模块是一个真正的数学模块,而不是传统浮点表示和浮点处理器的近似数学。我希望它是默认值,因为在字典中,我们在大多数语言中默认得到的近似浮点数学应该是无用定义的第一个示例。
>>repr(0.33245794180134)
给出了'0.33245794180133997'
。因此,我仍然无法保留最初的数字!尽管repr
肯定比str
@mcnemesis好:这属于“浮动不准确”定律。请注意,即使您发送了一个正好表示这个数字的字符串,web服务也可能会将其转换为浮点,并失去保存的精度。还要注意的是,差异是3e-17=0.00000000000000003,因此它可能无论如何都不重要。感谢“法律”,但我必须满足规范,这些值代表的地理位置精度损失,有时会受到处罚。不管怎样,这些提示是好的。@mcnemesis:赤道大约有40000000000毫米长。这大约是11个有效数字。如果你需要超过12个有效数字,你必须有一个非常有趣的应用程序。“精度”的损失更可能是由于使用了不适当的公式造成的。John很好地演示了为什么repr
更好。只有当要求说0.3334
不应等于0.3333
时,事情才会变得紧张起来。但我现在明白你的意思了。你为什么不使用format()
?如果你编辑你的问题,告诉我们(1)你是如何获得原始浮点值的(2)你为什么认为例如'0.33245794180134'
是最佳或所需的输出值(3)你的“规格”实际上说了什么(4)什么“有时给出惩罚的精度损失”意味着。放弃“十进制”业务。这没有什么帮助。另外,{0:.14f}。格式(lat)
工作得很好。@s.Lott:这是一个非常简单而且确实很好的方法。这是我在这个问题上采用的方法。我已经测试了'.14f'
和'{0:.14f}.格式(lat) >它们是非常好的和简单的!感谢这真的令人信服,尽管我的<代码> Python版本显示了<代码> Python 2.65。很好,你已经在我的首选方法上演示了<代码> RePr>代码>的一个很好的论证。我下次会考虑这个问题。是的,我现在真的开始接受这个更好的路径。因为目前,我的数据已经是浮点形式,这保留了(而且似乎提高了?)精度