Python 3.x rounding behavior

前端 未结 11 1630
别那么骄傲
别那么骄傲 2020-11-22 00:41

I was just re-reading What’s New In Python 3.0 and it states:

The round() function rounding strategy and return type have changed. Exact halfway cas

相关标签:
11条回答
  • 2020-11-22 01:02

    You can control the rounding you get in Py3000 using the Decimal module:

    >>> decimal.Decimal('3.5').quantize(decimal.Decimal('1'), 
        rounding=decimal.ROUND_HALF_UP)
    >>> Decimal('4')
    
    >>> decimal.Decimal('2.5').quantize(decimal.Decimal('1'),    
        rounding=decimal.ROUND_HALF_EVEN)
    >>> Decimal('2')
    
    >>> decimal.Decimal('3.5').quantize(decimal.Decimal('1'), 
        rounding=decimal.ROUND_HALF_DOWN)
    >>> Decimal('3')
    
    0 讨论(0)
  • 2020-11-22 01:03

    Just to add here an important note from documentation:

    https://docs.python.org/dev/library/functions.html#round

    Note

    The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float. See Floating Point Arithmetic: Issues and Limitations for more information.

    So don't be surprised to get following results in Python 3.2:

    >>> round(0.25,1), round(0.35,1), round(0.45,1), round(0.55,1)
    (0.2, 0.3, 0.5, 0.6)
    
    >>> round(0.025,2), round(0.035,2), round(0.045,2), round(0.055,2)
    (0.03, 0.04, 0.04, 0.06)
    
    0 讨论(0)
  • 2020-11-22 01:05

    Sample Reproduction:

    ['{} => {}'.format(x+0.5, round(x+0.5)) for x in range(10)]
    
    ['0.5 => 0', '1.5 => 2', '2.5 => 2', '3.5 => 4', '4.5 => 4', '5.5 => 6', '6.5 => 6', '7.5 => 8', '8.5 => 8', '9.5 => 10']
    

    API: https://docs.python.org/3/library/functions.html#round

    States:

    Return number rounded to ndigits precision after the decimal point. If ndigits is omitted or is None, it returns the nearest integer to its input.

    For the built-in types supporting round(), values are rounded to the closest multiple of 10 to the power minus ndigits; if two multiples are equally close, rounding is done toward the even choice (so, for example, both round(0.5) and round(-0.5) are 0, and round(1.5) is 2). Any integer value is valid for ndigits (positive, zero, or negative). The return value is an integer if ndigits is omitted or None. Otherwise the return value has the same type as number.

    For a general Python object number, round delegates to number.round.

    Note The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float. See Floating Point Arithmetic: Issues and Limitations for more information.

    Given this insight you can use some math to resolve it

    import math
    def my_round(i):
      f = math.floor(i)
      return f if i - f < 0.5 else f+1
    

    now you can run the same test with my_round instead of round.

    ['{} => {}'.format(x + 0.5, my_round(x+0.5)) for x in range(10)]
    ['0.5 => 1', '1.5 => 2', '2.5 => 3', '3.5 => 4', '4.5 => 5', '5.5 => 6', '6.5 => 7', '7.5 => 8', '8.5 => 9', '9.5 => 10']
    
    0 讨论(0)
  • 2020-11-22 01:07

    You can control the rounding you using the math.ceil module:

    import math
    print(math.ceil(2.5))
    > 3
    
    0 讨论(0)
  • 2020-11-22 01:08

    Try this code:

    def roundup(input):   
       demo = input  if str(input)[-1] != "5" else str(input).replace("5","6")
       place = len(demo.split(".")[1])-1
       return(round(float(demo),place))
    

    The result will be:

    >>> x = roundup(2.5)
    >>> x
    3.0  
    >>> x = roundup(2.05)
    >>> x
    2.1 
    >>> x = roundup(2.005)
    >>> x
    2.01 
    

    Ooutput you can check here: https://i.stack.imgur.com/QQUkS.png

    0 讨论(0)
提交回复
热议问题