使用 Floor/Ceil 将小数四舍五入为整数 5

Using Floor/Ceil to round decimals to integer of 5

我一直在使用下面的代码轻松舍入到 1dp,我需要 .5s 向上舍入,例如我想要 36.25 之类的值四舍五入为 36.3,而不是 36.2。

def my_round(n, ndigits=1):
    try:
       part = n * 10 ** ndigits
       delta = part - int(part)
       # always round "away from 0"
       if delta >= 0.5 or -0.5 < delta <= 0:
           part = math.ceil(part)
       else:
           part = math.floor(part)
       val =  part/(10 ** ndigits)
    except ValueError:
       val = np.nan
    return val

我现在需要将 df 中的不同小数列四舍五入为最接近的 5 个整数。谁能帮助建议我如何调整上面的原始代码来做到这一点?例如,我需要一个值,例如 702.5000 四舍五入到 705。使用正常的 Round() 它显然会变成 700。在这个例子中,所有其他正常的四舍五入规则应该适用,例如

702.222 to 700,
707.466 to 705,
703.021 to 705

def my_round(n):
    lower = (n//5)*5;
    upper = lower+5;

    if (n-lower)<(upper-n):
        return int(lower)
    return int(upper)

print(my_round(703.021))

上面的程序试图找出给定数字前后5的正确倍数。 然后它找到可能的下限和上限之间的差异以及 returns 差异最小的数字。这和四舍五入一样好。

您可以将要四舍五入的数字除以 5,然后取其 round() 并再次乘以五:

num = 707.466
int = num / 5 # returns 141.4932
rounded = round(int) # returns 141
answer = rounded * 5 # 705

或作为函数:

def round_to_five(num):
    num = num / 5
    num = round(num)
    return num * 5

希望对您有所帮助

# my standard point to which rounding shoulding happen
>>> standard_nums = [700, 702, 705, 708]


# example value I am taking
>>> my_num = 702.5 


# this is how I would round my number
>>> ret = abs(standard_nums[0] - my_num)
>>> val = standard_nums[0]
>>> for each in standard_nums[1:]:
...     if abs(each - my_num) < ret:
...             ret = abs(each - my_num)
...             val = each
...
>>> ret # min diff I can find
0.5
>>> val # value you are lookin for
702
>>>

## this above has a complexity of O(N)
## where N is the size of your standard number

最快的方法是除以 5,四舍五入,然后乘以 5。这完全是数学事实。

5*round(n/5)

并且不需要 if 语句决定何时使用 floorceil,因为 round 已经默认为该逻辑。

编辑:正如所指出的那样,这适用于所有值,除了那些在要求四舍五入时以 2.5 结尾的值(实际上许多示例不需要这个)。

由于 Ashwin 的回答已经完成了这一点,我将在没有函数定义的情况下在一行中进行修复,尽管它并不漂亮:

5 * (int(x/5) + 1 - round(x/5 % 1))

或使用 ceil 稍微清洁一些:

5*(math.ceil(x/5) - round(x/5 % 1))

利用 round 的行为正如我们从上面所希望的那样。 更好的是,定义:

def my_round(x): return int(x + 1) - round(x % 1)
def round5(x): return 5*my_round(x/5)

到 'fix' round 函数并在 2 行中创建一个漂亮的 round5 函数。这就是我要做的。

要四舍五入到一定的小数位,使用这个:

def my_round(x: float, round_to: float = 5, dp: int = 0) -> float: 
    round_to *= 10**dp 
    x *= 10**dp 
    return ((x + round_to / 2) // round_to * round_to) / 10**dp 

正在测试:

values = [702.500, 702.222, 707.466, 703.021]
targets = [705., 700., 705., 705.]
assert [my_round(x, 5, 0) for x in values] == targets
assert my_round(3.25, 0.1, 1) == 36.3

假设您使用 Python 3,下面的行可以完成这项工作吗?

5*(x//5)+5*(x%5>=2.5)

它似乎适用于 x 作为标量,numpy.arraypandas.series