python 为什么以及如何截断数值数据?

发布于 2024-11-03 01:22:37 字数 752 浏览 4 评论 0原文

我在这里处理两个变量,但很困惑,因为当我想将它们作为 URL 参数按原样发送时,它们的值似乎正在变化(它们失去了精度)。

看看我在 python 解释器中重现的这个场景:

>>> lat = 0.33245794180134
>>> long = 32.57355093956
>>> lat
0.33245794180133997
>>> long
32.57355093956
>>> nl = str(lat)
>>> nl '0.332457941801'
>>> nlo = str(long)
>>> nlo '32.5735509396'

那么发生了什么?如何确保当我将 latlong 序列化为字符串并将它们作为 url 查询字符串的一部分发送时,我不会丢失它们的精确精度?

为了澄清这种情况:

  1. 数据最初作为浮点数(在集合中)从另一个通过计算创建它们的模块进入我的模块。
  2. 精度在这里是一个敏感问题,因为这些数据用于进行各种跟踪和监控,错误的值可能会导致误报或不必要的警报。
  3. 如果不将数据序列化为字符串,就无法将数据发送到目标引擎(通过 Restiful api 进行侦听)(因此我可以将它们作为参数放入查询字符串中)

所以我需要的是转换的最佳方法浮入字符串,精度/信息损失最小。

Am dealing with two variables here, but confused because their values seem to be changing (they loose precision) when I want to send them as URL parameters as they are.

Look at this scenario as I reproduce it here from the python interpreter:

>>> lat = 0.33245794180134
>>> long = 32.57355093956
>>> lat
0.33245794180133997
>>> long
32.57355093956
>>> nl = str(lat)
>>> nl '0.332457941801'
>>> nlo = str(long)
>>> nlo '32.5735509396'

So what is happening? and how can I ensure that when I serialize lat and long to strings and send them as part of a url's query string I don't lose their exact precision?

To clarify the situation:

  1. The data originally comes to my module as floats (in a collection) from another module that creates them from calculations.
  2. Precision is a sensitive issue here because this data is being used to do tracking and monitoring of sorts and wrong values might cause false-positives or unnecessary alarms.
  3. There is no way to send the data over to the target engine (which listens via a restiful api) without serializing the data to strings (so i can place them in a query string as params)

So what I needed was the best way to transform floats into strings with minimal loss of precision / information.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一个人的旅程 2024-11-10 01:22:37

一般来说,如果您使用'%.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
>>>

2.7 之前的 Python 使用 17 位有效十进制数字生成 repr(a_float),因为这将保证 float(repr(a_float)) == a_float。新方法是使用提供相同保证的最少位数。按照 此链接 并按 Ctrl-F 搜索 repr()

如果您从外部源获取这些数字,那么您可能会通过浮动它们然后使用 14 位十进制数字的精度序列化它们来丢失精度。

如果您通过计算获得这些数字,那么使用 14 位十进制数字的精度序列化它们可能会损失精度。

摘要:一般来说,如果您使用 '%.14f' % lat,就会失去精度——不是 Python,不是浮点算术,而是您自己。

In general if you use '%.14f' % lat, you are LOSING PRECISION.

To get full precision from a float, use repr().

Example:

>>> lat = 1/3.
>>> lat
0.3333333333333333
>>> str(lat).count('3')
12
>>> ('%.14f' % lat).count('3')
14
>>> repr(lat).count('3')
16
>>>

By the way, you are using an old Python.

>>> 0.33245794180134 == 0.33245794180133997
True
>>>

Pythons before 2.7 produce repr(a_float) by using 17 significant decimal digits because that will guarantee that float(repr(a_float)) == a_float. The new method is to use the smallest number of digits that will provide the same guarantee. Follow this link and Ctrl-F search for repr().

If you are getting those numbers from an external source, then you could be losing precision by floating them and then serialising them with 14 decimal digits of precision.

If you are getting those numbers by calculation, then you could be losing precision by serialising them with 14 decimal digits of precision.

Summary: In general if you use '%.14f' % lat, YOU are losing precision -- not Python, not floating-point arithmetic, it's you..

滿滿的愛 2024-11-10 01:22:37

您可以尝试使用字符串格式来获得所需的精度。

>>> lat = 0.33245794180134
>>> lat
0.33245794180134
>>> "%.14f" % lat
'0.33245794180134'
>>> 

编辑以合并评论:

>>> '{0:.14f}'.format(lat)
'0.33245794180134'
>>> 

You can try using string formatting to get desired precision.

>>> lat = 0.33245794180134
>>> lat
0.33245794180134
>>> "%.14f" % lat
'0.33245794180134'
>>> 

edit to incorporate comments:

>>> '{0:.14f}'.format(lat)
'0.33245794180134'
>>> 
夜司空 2024-11-10 01:22:37

str 用于人类可读的表示。它很少产生与产生输入值的表达式等效或相似的东西。另一方面,repr 正是为此而明确的。事实上,REPL 就是用它来提供有关表达式结果的反馈。

请注意,尽管浮点数仍然具有有限精度,并且无法准确表示某些数字,无论您如何将它们序列化为字符串。

str is for human-readable representations. It rarely produces something that's equivalent or similar to an expression that produces the value fed to it. repr, on the other hand, is explicitly for that. In fact, it's what the REPL uses to give feedback about the results of expressions.

Note though that floats are still of finite precision and can't represent certain numbers exactly, regardless of how you serialize them to strings.

握住你手 2024-11-10 01:22:37

python 标准库十进制模块中的 Decimal 类型绝对是您想要的。默认情况下,它允许您保持 28 位精度,但不会强制将数字转换为二进制浮点表示形式。 Decimal 类型还允许涉及其他类型的数字的数学运算,而无需转换。

您的示例转换为十进制:

>>> 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 标准库中的十进制模块是一个真正的数学模块,而不是使用传统浮点得到的数学近似值点表示和浮点处理器。我希望它是默认值,因为在字典中,我们在大多数语言中默认获得的近似浮点数学应该是无用定义的第一个例子。

The Decimal type from the python standard library decimal module is definitely what you want. It allows you to keep up 28 digits of precision by default but doesn't force numbers into a binary floating point representation. The Decimal type also allows for mathematical operations involving numbers of other types without requiring conversion.

Your example converted to Decimal:

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

Adding a number to a Decimal:

>>> lat + 2
Decimal('2.33245794180134')

Avoiding the imprecision of binary floating point representations of numbers like 1.1:

>>> onepointone = decimal.Decimal(repr(1.1))
>>> onepointone
Decimal('1.1')

The decimal module in the python standard library is a real math module rather than the approximation of math you get with traditional floating point representations and floating point processors. I wish it was the default because in the dictionary the approximation floating point math we get by default in most languages should be the first example of the definition of useless.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文