Round number to nearest integer

前端 未结 11 2136
傲寒
傲寒 2020-11-27 12:32

I\'ve been trying to round long float numbers like:

32.268907563;
32.268907563;
31.2396694215;
33.6206896552;
...

With no success so far. I

11条回答
  •  甜味超标
    2020-11-27 13:25

    int(round(x))
    

    Will round it and change it to integer

    EDIT:

    You are not assigning int(round(h)) to any variable. When you call int(round(h)), it returns the integer number but does nothing else; you have to change that line for:

    h = int(round(h))
    

    To assign the new value to h

    EDIT 2:

    As @plowman said in the comments, Python's round() doesn't work as one would normally expect, and that's because the way the number is stored as a variable is usually not the way you see it on screen. There are lots of answers that explain this behavior:

    round() doesn't seem to be rounding properly

    One way to avoid this problem is to use the Decimal as stated by this answer: https://stackoverflow.com/a/15398691/4345659

    In order for this answer to work properly without using extra libraries it would be convenient to use a custom rounding function. After a lot of corrections, I came up with the following solution, that as far as I tested avoided all the storing issues. It is based on using the string representation, obtained with repr() (NOT str()!). It looks hacky but it was the only way I found to solve all the cases. It works with both Python2 and Python3.

    def proper_round(num, dec=0):
        num = str(num)[:str(num).index('.')+dec+2]
        if num[-1]>='5':
            return float(num[:-2-(not dec)]+str(int(num[-2-(not dec)])+1))
        return float(num[:-1])
    

    Tests:

    >>> print(proper_round(1.0005,3))
    1.001
    >>> print(proper_round(2.0005,3))
    2.001
    >>> print(proper_round(3.0005,3))
    3.001
    >>> print(proper_round(4.0005,3))
    4.001
    >>> print(proper_round(5.0005,3))
    5.001
    >>> print(proper_round(1.005,2))
    1.01
    >>> print(proper_round(2.005,2))
    2.01
    >>> print(proper_round(3.005,2))
    3.01
    >>> print(proper_round(4.005,2))
    4.01
    >>> print(proper_round(5.005,2))
    5.01
    >>> print(proper_round(1.05,1))
    1.1
    >>> print(proper_round(2.05,1))
    2.1
    >>> print(proper_round(3.05,1))
    3.1
    >>> print(proper_round(4.05,1))
    4.1
    >>> print(proper_round(5.05,1))
    5.1
    >>> print(proper_round(1.5))
    2.0
    >>> print(proper_round(2.5))
    3.0
    >>> print(proper_round(3.5))
    4.0
    >>> print(proper_round(4.5))
    5.0
    >>> print(proper_round(5.5))
    6.0
    >>> 
    >>> print(proper_round(1.000499999999,3))
    1.0
    >>> print(proper_round(2.000499999999,3))
    2.0
    >>> print(proper_round(3.000499999999,3))
    3.0
    >>> print(proper_round(4.000499999999,3))
    4.0
    >>> print(proper_round(5.000499999999,3))
    5.0
    >>> print(proper_round(1.00499999999,2))
    1.0
    >>> print(proper_round(2.00499999999,2))
    2.0
    >>> print(proper_round(3.00499999999,2))
    3.0
    >>> print(proper_round(4.00499999999,2))
    4.0
    >>> print(proper_round(5.00499999999,2))
    5.0
    >>> print(proper_round(1.0499999999,1))
    1.0
    >>> print(proper_round(2.0499999999,1))
    2.0
    >>> print(proper_round(3.0499999999,1))
    3.0
    >>> print(proper_round(4.0499999999,1))
    4.0
    >>> print(proper_round(5.0499999999,1))
    5.0
    >>> print(proper_round(1.499999999))
    1.0
    >>> print(proper_round(2.499999999))
    2.0
    >>> print(proper_round(3.499999999))
    3.0
    >>> print(proper_round(4.499999999))
    4.0
    >>> print(proper_round(5.499999999))
    5.0
    

    Finally, the corrected answer would be:

    # Having proper_round defined as previously stated
    h = int(proper_round(h))
    

    EDIT 3:

    Tests:

    >>> proper_round(6.39764125, 2)
    6.31 # should be 6.4
    >>> proper_round(6.9764125, 1)
    6.1  # should be 7
    

    The gotcha here is that the dec-th decimal can be 9 and if the dec+1-th digit >=5 the 9 will become a 0 and a 1 should be carried to the dec-1-th digit.

    If we take this into consideration, we get:

    def proper_round(num, dec=0):
        num = str(num)[:str(num).index('.')+dec+2]
        if num[-1]>='5':
          a = num[:-2-(not dec)]       # integer part
          b = int(num[-2-(not dec)])+1 # decimal part
          return float(a)+b**(-dec+1) if a and b == 10 else float(a+str(b))
        return float(num[:-1])
    

    In the situation described above b = 10 and the previous version would just concatenate a and b which would result in a concatenation of 10 where the trailing 0 would disappear. This version transforms b to the right decimal place based on dec, as a proper carry.

提交回复
热议问题