当前位置:  开发笔记 > 编程语言 > 正文

将浮点数限制为两个小数点

如何解决《将浮点数限制为两个小数点》经验,为你挑选了20个好方法。

我希望a四舍五入到13.95.

>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999

round功能不像我预期的那样工作.



1> Rex Logan..:

您遇到浮点数的旧问题,无法表示所有数字.命令行只显示内存中的完整浮点形式.

在浮点数中,您的圆形版本是相同的数字.由于计算机是二进制的,它们将浮点数存储为整数,然后将其除以2的幂,因此13.95将以与125650429603636838 /(2**53)类似的方式表示.

双精度数字具有53位(16位)的精度,而常规浮点数具有24位(8位)的精度.Python中的浮点使用双精度来存储值.

例如,

  >>> 125650429603636838/(2**53)
  13.949999999999999

  >>> 234042163/(2**24)
  13.949999988079071

  >>> a=13.946
  >>> print(a)
  13.946
  >>> print("%.2f" % a)
  13.95
  >>> round(a,2)
  13.949999999999999
  >>> print("%.2f" % round(a,2))
  13.95
  >>> print("{0:.2f}".format(a))
  13.95
  >>> print("{0:.2f}".format(round(a,2)))
  13.95
  >>> print("{0:.15f}".format(round(a,2)))
  13.949999999999999

如果您只有两位小数,那么您有几个更好的选择:1)使用整数并以美分存储值,而不是美元,然后除以100转换为美元.2)或使用十进制的固定点数.


@Christian存储的值与您显示该值的方式之间存在根本区别.格式化输出应该允许您根据需要添加填充,以及添加逗号分隔符等.
为什么人们总是在浮点舍入上采用货币?有时你只是想以较低的精度工作.
值得一提的是``%.2f'%round(a,2)`你不仅可以放在printf中,还可以输入像`str()这样的东西
@radtek:你没从字面上要求一个解释.最简单的解决方案确实是使用`Decimal`,那就是在这个答案提出的解决方案之一.另一个是转换的数量为整数并使用整数运算.这两种方法也出现在其他的答案和评论.
@radtek:您需要了解二进制值(类型为"float")只是十进制数的最接近可用近似值(您熟悉的是人类).没有这样的(有限可表示的)二进制值为0.245.它根本不存在,数学上**不能存在.最接近0.245的二进制值略小于**0.245,因此自然它向下舍入.同样地,二进制中没有0.225这样的东西,但是最接近0.225的二进制值稍微大于**0.225,所以自然它会向上舍入.
注意格式0是python 2.7或3.1中不需要的位置参数,我认为它是格式的一部分并得到奇怪的结果:)("{:.2f}".format(a)

2> Xolve..:

有新的格式规范,字符串格式规范迷你语言:

您可以这样做:

"{0:.2f}".format(13.949999999999999)

请注意,上面返回一个字符串.为了得到浮点数,只需用float(...):

float("{0:.2f}".format(13.949999999999999))

请注意,换行float()不会改变任何内容:

>>> x = 13.949999999999999999
>>> x
13.95
>>> g = float("{0:.2f}".format(x))
>>> g
13.95
>>> x == g
True
>>> h = round(x, 2)
>>> h
13.95
>>> x == h
True


要添加逗号你也可以``{0:,.2f}'.format(1333.949999999)`打印`'1,333.95'`.
@JossefHarush你可以用float()包装它,但你还没有获得任何东西.现在你又有了一个漂浮物,同样的不精确.13.9499999999999和13.95是相同的浮点数.
@NedBatchelder:我同意它们是相同的,但是这会将浮点数限制为两个小数点:)
顺便说一下,从Python 3.6开始,我们可以使用f字符串:`f“ Result is {result:.2f}”`

3> chribsen..:

内置round()在Python 2.7或更高版本中运行良好.

例:

>>> round(14.22222223, 2)
14.22

查看文档.


从Python 3文档页面:`注意float()的round()行为可能令人惊讶:例如,round(2.675,2)给出2.67,而不是预期的2.68。这不是错误:这是由于大多数十进制小数不能完全表示为浮点数的结果。

4> grant zukows..:

我觉得最简单的方法是使用该format()功能.

例如:

a = 13.949999999999999
format(a, '.2f')

13.95

这会产生一个浮点数作为一个四舍五入到两个小数点的字符串.



5> 小智..:

大多数数字不能用浮点数精确表示.如果你想要对数字进行舍入,因为这是你的数学公式或算法所需要的,那么你想要使用round.如果您只想将显示限制到一定的精度,那么甚至不要使用round,只需将其格式化为该字符串即可.(如果你想用一些替代的舍入方法显示它,并且有吨,那么你需要混合这两种方法.)

>>> "%.2f" % 3.14159
'3.14'
>>> "%.2f" % 13.9499999
'13.95'

最后,虽然也许最重要的是,如果你想要精确的数学,那么你根本不需要花车.通常的例子是处理货币并将"美分"存储为整数.



6> Alexey Anton..:

使用

print"{:.2f}".format(a)

代替

print"{0:.2f}".format(a)

因为后者在尝试输出多个变量时可能会导致输出错误(请参阅注释).


这是无稽之谈。给出的两个语句在Python 2.7上的行为相同,并且仅第二条语句在Python 2.6上有效。(这两个语句在Python 3或Python <2.6中均无效。)第一种形式除了简洁以外没有任何优势。
对于Python 3,您只需添加括号print(...).在他们内部我写的都是对的.
如果您有两个变量,您将在打印后("{0:.2f} {1:.2f}".format(a,b))

7> ax003d..:

请尝试以下代码:

>>> a = 0.99334
>>> a = int((a * 100) + 0.5) / 100.0 # Adding 0.5 rounds it up
>>> print a
0.99


如果`round()`不像OP提到的那样工作,那么@interjay是必要的.
如果采用这种方法,则应添加0.5以获得更准确的表示.int(a*100 + 0.5)/ 100.0; 使用math.ceil是另一种选择.
@ShashankSawant:嗯,首先,所呈现的答案不是圆的,它会截断.在最后添加一半的建议将会循环,但是这样做首先只使用`round`函数没有任何好处.另一方面,因为这个解决方案仍然使用浮点,OP的原始问题仍然存在,即使对于这个"解决方案"的"更正"版本也是如此.
-1,这只是`round`函数的不必要的重新实现(在问题中使用).

8> A.J...:

使用Python <3(例如2.6或2.7),有两种方法可以做到这一点.

# Option one 
older_method_string = "%.9f" % numvar

# Option two (note ':' before the '.9f')
newer_method_string = "{:.9f}".format(numvar)

但请注意,对于3以上的Python版本(例如3.2或3.3),选项2是首选.

有关选项二的更多信息,我建议使用Python文档中的字符串格式链接.

有关选项一的更多信息,此链接就足够了,并且有关于各种标志的信息.

参考:将浮点数转换为特定精度,然后复制到字符串



9> hynekcer..:

TLDR;)

输入/输出的舍入问题已由Python 2.7.03.1明确解决.

无限测试:

import random
from decimal import Decimal
for x in iter(random.random, None):           # Verify FOREVER that rounding is fixed :-)
    assert float(repr(x)) == x                # Reversible repr() conversion.
    assert float(Decimal(repr(x))) == x
    assert len(repr(round(x, 10))) <= 12      # Smart decimal places in repr() after round.
    if x >= 0.1:                              # Implicit rounding to 12 significant digits
        assert str(x) == repr(round(x, 12))   # by str() is good enough for small errors.
        y = 1000 * x                             # Decimal type is excessive for shopping
        assert str(y) == repr(round(y, 12 - 3))  # in a supermaket with Python 2.7+ :-)

文档

请参阅发行说明Python 2.7 - 其他语言更改第四段:

现在,在大多数平台上,浮点数和字符串之间的转换正确舍入.这些转换发生在许多不同的地方:浮点数上的str()和复数; 浮动和复杂的构造函数; 数字格式; 序列化使用和反序列化浮子和复数str -> float() -> repr() -> float() ...,Decimal -> float -> str -> Decimalstr()模块; 在Python代码中解析float和imaginary文字; 和十进制到浮点转换.

与此相关,浮点数x 的repr()现在返回基于最短十进制字符串的结果,该最小十进制字符串保证在正确的舍入下舍入到x(具有舍入到半舍入到舍入模式).以前它给出了一个基于舍入x到17个十进制数字的字符串.

相关问题


更多信息::marshal Python 2.7之前的格式与当前类似pickle.两种类型都使用相同的64位IEEE 754双精度和52位尾数.一个很大的区别是json经常使用过多的十进制数格式化,因此不会丢失任何位,但13.949999999999999和13.950000000000001之间不存在有效的IEEE 754编号.结果不好,转换float不可逆.另一方面:numpy.float64格式化,以便每个数字都很重要; 序列没有间隙,转换是可逆的.简单地说:如果您可能有一个numpy.float64数字,请将其转换为普通浮点数,以便为人类而不是数字处理器进行格式化,否则Python 2.7+不再需要它.



10> Greg Hewgill..:

您可以修改输出格式:

>>> a = 13.95
>>> a
13.949999999999999
>>> print "%.2f" % a
13.95



11> Asad Manzoor..:

您可以使用格式运算符将值四舍五入到python中的小数点后2位:

print(format(14.4499923, '.2f')) // output is 14.45


这将返回字符串

12> Matt Fletche..:

这里似乎没有人提到它,所以让我举一个Python 3.6的f-string/template-string格式的例子,我觉得它很漂亮:

>>> f'{a:.2f}'

它也可以用更长的例子,运算符而不需要parens:

>>> print(f'Completed in {time.time() - start:.2f}s')



13> Shashank Sin..:

在Python 2.7中:

a = 13.949999999999999
output = float("%0.2f"%a)
print output



14> nosklo..:

Python教程有一个名为Floating Point Arithmetic的附录:问题和限制.阅读.它解释了发生了什么以及为什么Python正在发挥最大作用.它甚至有一个与你相匹配的例子.让我引用一下:

>>> 0.1
0.10000000000000001

您可能想要使用该round() 功能将其切换回您期望的单个数字.但这没有区别:

>>> round(0.1, 1)
0.10000000000000001

问题是存储的二进制浮点值“0.1” 已经是最好的二进制近似值1/10,所以试图再次舍入它不能使它变得更好:它已经很好了.

另一个结果是,由于0.1 不完全相同1/10,总和十个值0.1可能不会完全屈服 1.0,或者:

>>> sum = 0.0
>>> for i in range(10):
...     sum += 0.1
...
>>> sum
0.99999999999999989

解决问题的另一种方法是使用该decimal模块.



15> toto_tico..:

正如@Matt指出的那样,Python 3.6提供了f字符串,它们也可以使用嵌套参数:

value = 2.34558
precision = 2
width = 4

print(f'result: {value:{width}.{precision}f}')

将显示 result: 2.35



16> HUAGHAGUAH..:

它正在完成你告诉它要做的事情并且正常工作.阅读有关浮点混淆的更多信息,也可以尝试使用十进制对象.



17> 小智..:

为了修复类型动态语言(如Python和JavaScript)中的浮点,我使用了这种技术

# For example:
a = 70000
b = 0.14
c = a * b

print c # Prints 980.0000000002
# Try to fix
c = int(c * 10000)/100000
print c # Prints 980

您还可以使用Decimal,如下所示:

from decimal import *
getcontext().prec = 6
Decimal(1) / Decimal(7)
# Results in 6 precision -> Decimal('0.142857')

getcontext().prec = 28
Decimal(1) / Decimal(7)
# Results in 28 precision -> Decimal('0.1428571428571428571428571429')



18> Jonathan L..:

结合使用Decimal对象和round()方法。

Python 3.7.3
>>> from decimal import Decimal
>>> d1 = Decimal (13.949999999999999) # define a Decimal
>>> d1 
Decimal('13.949999999999999289457264239899814128875732421875')
>>> d2 = round(d1, 2) # round to 2 decimals
>>> d2
Decimal('13.95')



19> MikeL..:
orig_float = 232569 / 16000.0

14.5355625

short_float = float("{:.2f}".format(orig_float)) 

14.54



20> weaming..:
from decimal import Decimal


def round_float(v, ndigits=2, rt_str=False):
    d = Decimal(v)
    v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits))
    if rt_str:
        return v_str
    return Decimal(v_str)

结果:

Python 3.6.1 (default, Dec 11 2018, 17:41:10)
>>> round_float(3.1415926)
Decimal('3.14')
>>> round_float(3.1445926)
Decimal('3.14')
>>> round_float(3.1455926)
Decimal('3.15')
>>> round_float(3.1455926, rt_str=True)
'3.15'
>>> str(round_float(3.1455926))
'3.15'

推荐阅读
拾味湖
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有