将浮点数限制为小数点后两位
我希望将 a
四舍五入为 13.95。 我尝试使用 round
,但我得到:
>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999
对于标准库 Decimal 类的类似问题,请参阅如何格式化小数以始终显示 2 位小数?.
I want a
to be rounded to 13.95. I tried using round
, but I get:
>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999
For the analogous issue with the standard library Decimal class, see How can I format a decimal to always show 2 decimal places?.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
您遇到了浮点数的老问题,即并非所有数字都可以准确表示。 命令行只是向您显示内存中的完整浮点形式。
对于浮点表示,您的舍入版本是相同的数字。 由于计算机是二进制的,它们将浮点数存储为整数,然后将其除以 2 的幂,因此 13.95 将以类似于 125650429603636838/(2**53) 的方式表示。
双精度数具有 53 位(16 位)精度,常规浮点数具有 24 位(8 位)精度。 Python 中的浮点类型使用双精度来存储值。
例如,
如果您仅在小数点后两位(例如,为了显示货币值),那么您有几个更好的选择:
You are running into the old problem with floating point numbers that not all numbers can be represented exactly. The command line is just showing you the full floating point form from memory.
With floating point representation, your rounded version is the same number. Since computers are binary, they store floating point numbers as an integer and then divide it by a power of two so 13.95 will be represented in a similar fashion to 125650429603636838/(2**53).
Double precision numbers have 53 bits (16 digits) of precision and regular floats have 24 bits (8 digits) of precision. The floating point type in Python uses double precision to store the values.
For example,
If you are after only two decimal places (to display a currency value, for example), then you have a couple of better choices:
有新的格式规范,字符串格式规范迷你语言:
您可以执行相同的操作:
注1:上面返回一个字符串。 为了获得浮动,只需用
float(...)
包装:注 2: 用
float()
包装不会改变任何事物:There are new format specifications, String Format Specification Mini-Language:
You can do the same as:
Note 1: the above returns a string. In order to get as float, simply wrap with
float(...)
:Note 2: wrapping with
float()
doesn't change anything:内置的 round() 在 Python 2.7 或更高版本中工作得很好。
示例:
查看文档。
The built-in
round()
works just fine in Python 2.7 or later.Example:
Check out the documentation.
让我举一个 Python 3.6 的 f-string/template- 的例子字符串格式,我认为它非常简洁:
它也适用于较长的示例,带有运算符并且不需要括号:
Let me give an example in Python 3.6's f-string/template-string format, which I think is beautifully neat:
It works well with longer examples too, with operators and not needing parentheses:
我觉得最简单的方法是使用
format()
函数。例如:
这会生成一个浮点数作为四舍五入到小数点后两位的字符串。
I feel that the simplest approach is to use the
format()
function.For example:
This produces a float number as a string rounded to two decimal points.
大多数数字无法用浮点数精确表示。 如果您想对数字进行舍入,因为这是您的数学公式或算法所需要的,那么您需要使用舍入。 如果您只想将显示限制为一定的精度,那么甚至不要使用 round 并将其格式化为该字符串。 (如果您想使用某种替代舍入方法来显示它,并且有很多舍入方法,那么您需要混合使用这两种方法。)
最后,也许最重要的是,如果您想要精确数学,那么您根本不想要漂浮物。 通常的例子是处理金钱并将“分”存储为整数。
Most numbers cannot be exactly represented in floats. If you want to round the number because that's what your mathematical formula or algorithm requires, then you want to use round. If you just want to restrict the display to a certain precision, then don't even use round and just format it as that string. (If you want to display it with some alternate rounding method, and there are tons, then you need to mix the two approaches.)
And lastly, though perhaps most importantly, if you want exact math then you don't want floats at all. The usual example is dealing with money and to store 'cents' as an integer.
使用
而不是
因为后者在尝试输出多个变量时可能会导致输出错误(请参阅注释)。
Use
instead of
Because the latter may lead to output errors when trying to output multiple variables (see comments).
TLDR ;)
输入和输出的舍入问题已由 Python 3.1 明确解决,并且该修复也向后移植到 Python 2.7.0。
四舍五入数字可以在浮点数和字符串之间可逆转换:
str-> 浮动() - > repr() ->; float() ...
或十进制 -> 浮动-> str-> Decimal
存储不再需要
Decimal
类型。算术运算的结果必须再次四舍五入,因为四舍五入错误可能会累积比解析一个数字后可能出现的错误更多的错误。 改进的
repr()
算法无法解决这个问题(Python >= 3.1,>= 2.7.0):输出字符串函数
str(float(...))< /code> 在 Python 中四舍五入为 12 位有效数字 < 2.7 倍且 < 3.1,防止过多的无效数字,类似于未固定的 repr() 输出。 在减去非常相似的数字之后,这仍然是不够的,并且在其他操作之后它又被舍入太多了。 Python 2.7 和 3.1 使用相同长度的 str(),尽管 repr() 是固定的。 一些旧版本的 Numpy 也存在过多的无效数字,即使使用固定的 Python 也是如此。 当前的 Numpy 是固定的。 Python 版本 >= 3.2 具有相同的 str() 和 repr() 函数结果以及 Numpy 中类似函数的输出。
测试
文档
请参阅发行说明 Python 2.7 - 其他语言更改 第四段:
相关问题
更多信息:
float
Python 2.7 之前的版本与当前的 numpy.float64 类似。 两种类型都使用相同的 64 位 IEEE 754 双精度和 52 位尾数。 一个很大的区别是np.float64.__repr__
经常使用过多的十进制数字进行格式化,以便不会丢失任何位,但在 13.9499999999999999 和 13.950000000000001 之间不存在有效的 IEEE 754 数字。 结果并不好,并且 numpy 的转换repr(float(number_as_string))
不可逆。 另一方面:float.__repr__
的格式使得每个数字都很重要; 序列没有间隙并且转换是可逆的。 简单地说:如果您可能有一个 numpy.float64 数字,请将其转换为普通浮点数,以便为人类而不是数字处理器格式化,否则 Python 2.7+ 不需要更多。TLDR ;)
The rounding problem of input and output has been solved definitively by Python 3.1 and the fix is backported also to Python 2.7.0.
Rounded numbers can be reversibly converted between float and string back and forth:
str -> float() -> repr() -> float() ...
orDecimal -> float -> str -> Decimal
A
Decimal
type is not necessary for storage anymore.Results of arithmetic operations must be rounded again because rounding errors could accumulate more inaccuracy than that is possible after parsing one number. That is not fixed by the improved
repr()
algorithm (Python >= 3.1, >= 2.7.0):The output string function
str(float(...))
was rounded to 12 valid digits in Python < 2.7x and < 3.1, to prevent excessive invalid digits similar to unfixed repr() output. That was still insufficientl after subtraction of very similar numbers and it was too much rounded after other operations. Python 2.7 and 3.1 use the same length of str() although the repr() is fixed. Some old versions of Numpy had also excessive invalid digits, even with fixed Python. The current Numpy is fixed. Python versions >= 3.2 have the same results of str() and repr() function and also output of similar functions in Numpy.Test
Documentation
See the Release notes Python 2.7 - Other Language Changes the fourth paragraph:
The related issue
More information: The formatting of
float
before Python 2.7 was similar to the currentnumpy.float64
. Both types use the same 64 bit IEEE 754 double precision with 52 bit mantissa. A big difference is thatnp.float64.__repr__
is formatted frequently with an excessive decimal number so that no bit can be lost, but no valid IEEE 754 number exists between 13.949999999999999 and 13.950000000000001. The result is not nice and the conversionrepr(float(number_as_string))
is not reversible with numpy. On the other hand:float.__repr__
is formatted so that every digit is important; the sequence is without gaps and the conversion is reversible. Simply: If you perhaps have a numpy.float64 number, convert it to normal float in order to be formatted for humans, not for numeric processors, otherwise nothing more is necessary with Python 2.7+.尝试下面的代码:
Try the code below:
使用:
这将返回;
说明:
round函数有两个参数;
要四舍五入的数字和要返回的小数位数。 这里我返回了两位小数。
Use:
This will return;
Explanation:
The round function takes two arguments;
The number to be rounded and the number of decimal places to be returned. Here I returned two decimal places.
您可以修改输出格式:
You can modify the output format:
与Python< 3(例如2.6或2.7),有两种方法可以做到这一点。
但请注意,对于 3 以上的 Python 版本(例如 3.2 或 3.3),选项二是 首选。
有关选项二的更多信息,我建议此链接位于 Python 文档中的字符串格式< /a>.
有关选项一的更多信息,此链接就足够了,并且包含有关各种标志。
参考:将浮点数转换为一定的精度,然后复制到字符串
With Python < 3 (e.g. 2.6 or 2.7), there are two ways to do so.
But note that for Python versions above 3 (e.g. 3.2 or 3.3), option two is preferred.
For more information on option two, I suggest this link on string formatting from the Python documentation.
And for more information on option one, this link will suffice and has information on the various flags.
Reference: Convert floating point number to a certain precision, and then copy to string
您可以使用 format 运算符将值四舍五入到小数点后两位在Python中:
You can use format operator for rounding the value up to two decimal places in Python:
正如 Matt 指出的,Python 3.6 提供了f-strings,并且它们还可以使用 嵌套参数:
将显示
结果:2.35
As Matt pointed out, Python 3.6 provides f-strings, and they can also use nested parameters:
which will display
result: 2.35
在 Python 2.7 中:
In Python 2.7:
我们有多种选择来做到这一点:
选项 1:
选项 2:
内置的 round() 支持 Python 2.7 或更高版本。
We multiple options to do that:
Option 1:
Option 2:
The built-in round() supports Python 2.7 or later.
Python 教程有一个名为浮点算术:问题和限制。 阅读。 它解释了正在发生的事情以及为什么 Python 会尽力而为。 它甚至还有一个与您的示例相匹配的示例。 让我引用一下:
解决问题的一种替代方法和解决方案是使用 <代码>十进制模块。
The Python tutorial has an appendix called Floating Point Arithmetic: Issues and Limitations. Read it. It explains what is happening and why Python is doing its best. It has even an example that matches yours. Let me quote a bit:
One alternative and solution to your problems would be using the
decimal
module.使用 Decimal 对象和 round() 方法的组合。
Use combination of Decimal object and round() method.
对于原始 Python:
对于浮点到字符串转换 2 位小数:
对于浮点到浮点转换 2 位小数:
For Raw Python:
For float to string converted 2 decimal points:
For float to float converted 2 decimal points:
它完全按照您的指示进行操作并且工作正常。 阅读有关浮点混淆的更多信息,也许可以尝试decimal 对象代替。
It's doing exactly what you told it to do and is working correctly. Read more about floating point confusion and maybe try decimal objects instead.
结果:
Results:
使用像这样的 lambda 函数:
这样你就可以这样做:
并得到
Use a lambda function like this:
This way you could just do:
and get
它很简单,例如:
使用 decimal 模块快速正确舍入小数浮点运算:
<预置><代码> d = 十进制(10000000.0000009)
实现四舍五入:
结果为
Decimal('10000000.00')
使上述内容 干燥:
或
PS:对他人的批评: 格式不四舍五入。
It's simple like:
use decimal module for fast correctly-rounded decimal floating point arithmetic:
to achieve rounding:
will result with
Decimal('10000000.00')
make the above DRY:
or
PS: critique of others: formatting is not rounding.
简单的解决方案就在这里
The simple solution is here
为了修复 Python 和 JavaScript 等动态类型语言中的浮点,我使用这种技术
您也可以使用 Decimal,如下所示:
For fixing the floating point in type-dynamic languages such as Python and JavaScript, I use this technique
You can also use Decimal as following:
这是使用格式的简单解决方案 功能。
注意:我们将数字转换为浮点数,因为 format 方法返回一个字符串。
Here is the simple solution using the format function.
Note: We are converting numbers to float, because the format method is returning a string.
如果你想处理金钱,请使用 Python decimal 模块:
If you want to handle money, use the Python decimal module:
为我工作了很多年,使用多种语言。
has worked for me for many years in many languages.
要将数字舍入为分辨率,最好的方法是以下方法,它可以使用任何分辨率(0.01 表示两位小数,甚至其他步长):
To round a number to a resolution, the best way is the following one, which can work with any resolution (0.01 for two decimals or even other steps):