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

Python 将浮点限制为两个小数点,python,floating-point,rounding,precision,Python,Floating Point,Rounding,Precision,我希望a四舍五入到13.95 该函数的工作方式与我预期的不同。您遇到的是浮点数字,并非所有数字都可以精确表示。命令行只是显示内存中的完整浮点形式 使用浮点表示法时,舍入的版本是相同的数字。由于计算机是二进制的,它们将浮点数存储为整数,然后将其除以二的幂,因此13.95将以类似于125650429636838/(2**53)的方式表示 双精度数字具有53位(16位)的精度,常规浮点数具有24位(8位)的精度。用于存储值的 比如说, >>> 125650429603636838/(

我希望
a
四舍五入到13.95

该函数的工作方式与我预期的不同。

您遇到的是浮点数字,并非所有数字都可以精确表示。命令行只是显示内存中的完整浮点形式

使用浮点表示法时,舍入的版本是相同的数字。由于计算机是二进制的,它们将浮点数存储为整数,然后将其除以二的幂,因此13.95将以类似于125650429636838/(2**53)的方式表示

双精度数字具有53位(16位)的精度,常规浮点数具有24位(8位)的精度。用于存储值的

比如说,

>>> 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("{:.2f}".format(a))
13.95
>>> print("{:.2f}".format(round(a, 2)))
13.95
>>> print("{:.15f}".format(round(a, 2)))
13.949999999999999
如果仅在小数点后两位(例如,显示货币值),则有两个更好的选择:

  • 使用整数并以美分(而不是美元)存储值,然后除以100转换为美元
  • 或者使用固定点数,如

  • 您可以修改输出格式:

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

    它完全按照你告诉它的去做,并且工作正常。请阅读更多有关对象的信息,或者尝试使用对象。

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


    最后,也许最重要的是,如果你想要精确的数学,那么你根本就不想要浮点数。通常的例子是处理金钱和将“美分”存储为整数。

    Python教程有一个附录,名为。读一下。它解释了正在发生的事情以及Python为什么会做到最好。它甚至有一个与你的例子相匹配的例子。让我引述一点:

    您可能会尝试使用
    round()
    函数将其切回单个 你期望的数字。但这并不重要 区别:

    >>> round(0.1, 1)
    0.10000000000000001
    
    问题是二进制文件 为
    “0.1”
    已经是最好的二进制文件了 近似于
    1/10
    ,因此尝试 再绕一圈也不能让它变得更好: 这已经是最好的了

    另一个结果是因为
    0.1
    不完全是
    1/10
    ,求和10
    0.1
    的值可能无法精确生成
    1.0
    ,或者:

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

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

    有新的格式规范:

    您可以执行以下操作:

    "{:.2f}".format(13.949999999999999)
    
    注意1:上面返回一个字符串。为了获得浮点值,只需使用
    float(…)

    注意2:使用
    float()包装不会改变任何内容:

    >>> x = 13.949999999999999999
    >>> x
    13.95
    >>> g = float("{:.2f}".format(x))
    >>> g
    13.95
    >>> x == g
    True
    >>> h = round(x, 2)
    >>> h
    13.95
    >>> x == h
    True
    
    请尝试以下代码:

    >>> a = 0.99334
    >>> a = int((a * 100) + 0.5) / 100.0 # Adding 0.5 rounds it up
    >>> print a
    0.99
    
    对于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),选项二是

    有关选项二的更多信息,我建议在上链接

    有关选项一的更多信息


    参考:

    为了修复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
    
    您还可以使用十进制,如下所示:

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

    我觉得最简单的方法是使用
    format()
    函数

    例如:

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

    这将生成一个四舍五入到两个小数点的字符串形式的浮点数。

    要将数字四舍五入到一个分辨率,最好的方法是使用以下方法,可以使用任何分辨率(0.01表示两个小数点或甚至其他步骤):


    我使用的方法是字符串切片。这是相对快速和简单的

    首先,将浮点值转换为字符串,然后选择希望的长度

    float = str(float)[:5]
    
    在上面的一行中,我们将值转换为字符串,然后仅保留字符串的前四位数字或字符(包括)

    希望有帮助

    TLDR;) Python 2.7.0和3.1最终解决了输入/输出的舍入问题

    正确舍入的数字可以可逆地来回转换:
    str->float()->repr()->float()…
    Decimal->float->str->Decimal

    存储不再需要十进制类型


    (当然,可能需要对四舍五入数字的加减结果进行四舍五入,以消除累积的最后一位错误。显式十进制算法仍然很方便,但通过
    str()
    (即四舍五入到12个有效数字)转换为字符串如果不需要极端精度或连续算术运算的极端次数,则通常足够好。)

    无限测试

    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+ :-)
    
    value = 2.34558
    precision = 2
    width = 4
    
    print(f'result: {value:{width}.{precision}f}')
    
    随机导入
    从十进制输入十进制
    对于iter中的x(random.random,None):#永远验证舍入是固定的:-)
    断言浮点(repr(x))==x#可逆repr()转换。
    断言浮点(十进制(repr(x))==x
    断言len(repr(舍入(x,10)))=0.1:#隐式舍入到12位有效数字
    assert str(x)=repr(round(x,12))#by str()对于小错误来说已经足够好了。
    y=1000*x#对于购物来说,十进制类型太多了
    assert str(y)=repr(round(y,12-3))#在使用Python 2.7+的超级市场中:-)
    
    文档 见第四段:

    在大多数平台上,浮点数和字符串之间的转换现在已正确舍入。这些转换发生在许多不同的地方:浮点数和复数上的str();浮华与复杂
    a = 13.949999999999999
    format(a, '.2f')
    
    13.95
    
    >>> import numpy as np
    >>> value = 13.949999999999999
    >>> resolution = 0.01
    >>> newValue = int(np.round(value/resolution))*resolution
    >>> print newValue
    13.95
    
    >>> resolution = 0.5
    >>> newValue = int(np.round(value/resolution))*resolution
    >>> print newValue
    14.0
    
    float = str(float)[:5]
    
    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+ :-)
    
    >>> round(14.22222223, 2)
    14.22
    
    print"{:.2f}".format(a)
    
    print"{0:.2f}".format(a)
    
    orig_float = 232569 / 16000.0
    
    short_float = float("{:.2f}".format(orig_float)) 
    
    >>> f'{a:.2f}'
    
    >>> print(f'Completed in {time.time() - start:.2f}s')
    
    value = 2.34558
    precision = 2
    width = 4
    
    print(f'result: {value:{width}.{precision}f}')
    
    a = 13.949999999999999
    output = float("%0.2f"%a)
    print output
    
    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'
    
       d.quantize(Decimal('0.01'))
    
        def round_decimal(number, exponent='0.01'):
            decimal_value = Decimal(number)
            return decimal_value.quantize(Decimal(exponent))
    
        def round_decimal(number, decimal_places=2):
            decimal_value = Decimal(number)
            return decimal_value.quantize(Decimal(10) ** -decimal_places)
    
    print(format(14.4499923, '.2f')) // output is 14.45
    
    arred = lambda x,n : x*(10**n)//1/(10**n)
    
    arred(3.141591657,2)
    
    3.14
    
    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')
    
    import decimal
            
    def value_to_decimal(value, decimal_places):
        decimal.getcontext().rounding = decimal.ROUND_HALF_UP  # define rounding method
        return decimal.Decimal(str(float(value))).quantize(decimal.Decimal('1e-{}'.format(decimal_places)))
    
    x = 1.090675765757
    g = float("{:.2f}".format(x))
    print(g)
    
    x = 1.090675765757
    g =  round(x, 2)
    print(g)
    
    float_number = 12.234325335563
    round(float_number, 2)
    
    12.23
    
    from decimal import Decimal, ROUND_HALF_UP
    
    # amount can be integer, string, tuple, float, or another Decimal object
    def to_money(amount) -> Decimal:
        money = Decimal(amount).quantize(Decimal('.00'), rounding=ROUND_HALF_UP)
        return money