【问题标题】:Python - how to round up to specified decimalPython - 如何四舍五入到指定的小数
【发布时间】:2020-10-20 16:09:12
【问题描述】:

我想将 Python 中的数字四舍五入到指定的小数。

例如,如果我选择

(2.1, 0.2) -->  I want to get 2.2 
(2.2, 0.2) -->  I want to get 2.2 
(3.6, 0.5) -->  I want to get 4.0
(3.5, 0.5) -->  I want to get 3.5

【问题讨论】:

  • 这能回答你的问题吗? Round integers to the nearest 10
  • 你确定你的第三个输出吗?我希望它是 3.5
  • @mathfux 我想第二个值是他/她决定四舍五入的阈值。 3.6 - 3 = 0.6 > 0.5。
  • @mathfux 检查我的解决方案
  • @Nikaido 问题中没有提到。它可能有不同的方式:rounder(x, y) 是最接近xy 的倍数。如果有两个这样的倍数,请选择绝对值较高的那个。

标签: python numpy rounding


【解决方案1】:

可能不是最有效的,但使用 numpy

我假设您使用的小数不多

import numpy as np 

def rounder(num, round_):
   int_p = np.floor(num)
   float_p = num - int_p
   print(float_p) # this print is meant to show the floating point problem
   diff  = float_p - round_
   if diff <= 0 or -0.00001 <diff< 0.00001:
       return int_p + round_
   else:
       return np.ceil(num)

 list_ = [(2.1, 0.2), (2.2, 0.2), (3.6, 0.5), (3.5, 0.5)]

 for num, round_ in list_:
     print("({}, {})".format(num, round_), rounder(num, round_))

 
 # (2.1, 0.2) 2.2
 # (2.2, 0.2) 2.2
 # (3.6, 0.5) 4.0
 # (3.5, 0.5) 3.5

不幸的是,浮点的表示存在问题,不那么精确。这就是为什么我在 if else -0.00001 &lt;diff&lt; 0.00001 中写了另一个条件的原因,这意味着,如果差异不是那么高(接近于零),那么它基本上是零

op 要求的新算法

import numpy as np 

def rounder(num, round_):
  int_p = np.floor(num)
  new_value = int_p
  while new_value < num:
    new_value = round(new_value + round_, 4)
  return new_value


list_ = [(2.1, 0.2), (2.2, 0.2), (3.6, 0.5), (3.5, 0.5), (0.178, 0.1)]

for num, round_ in list_:
    print("({}, {})".format(num, round_), rounder(num, round_))


# (2.1, 0.2) 2.2
# (2.2, 0.2) 2.2
# (3.6, 0.5) 4.0
# (3.5, 0.5) 3.5
# (0.178, 0.1) 0.2

【讨论】:

  • 经过第二次检查,它没有给出正确的结果:print(rounder(0.178,0.1)) 应该给出 0.2 但给出 1.0
  • @Jeroen 让我检查一下
  • @Jeroen 那么我不明白你到底想要什么。在您的示例中,对于值 (3.6, 0.5),您为什么会得到 4?
  • 对于我所理解的,对于值 (0.178, 0.1) 我应该得到 1
  • 对于 (3.6, 0.5) 我确实想要 (4.0)。将下一个值四舍五入为 0.5 的乘积。那么对于 (0.178, 0.1) 我们有可能的候选者 (0,0.1,0.2,0.3) --> 所以这将是 0.2。只有当数字等于 r ound_ 的乘积时,我才想保持数字
【解决方案2】:

我想要的是:

def rounder(num, round_):
    val = num // round_   
    if val*round_  == num:
        return num
    else:
        return val*round_ + round_ 
    
list_ = [(9.3, 0.4), (2.2, 0.2), (3.6, 0.5), (3.5, 0.5), (0.178, 0.1)]

for num, round_ in list_:
    print("({}, {})".format(num, round_), rounder(num, round_))

【讨论】:

    【解决方案3】:

    假设rounder(x, y) 是最接近x 的y 的倍数。如果有两个这样的倍数,请选择绝对值较高的那个。

    Python 存在四舍五入的问题:

    >>> round(10.5)
    10
    >>> np.round(10.5)
    10.0
    

    可迭代案例

    借用this simple fix,我会为OP的问题扩展它

    import math
    def rounder(x, y):
        r = x/y
        if (r - int(r) >= 0.5):
            return y * math.ceil(r)
        else:
            return y * math.floor(r)
    

    示例运行:

    >>> rounder(2.1, 0.2)
    2.2
    >>> rounder(2.2, 0.2)
    2.2
    >>> rounder(3.6, 0.5)
    3.5
    >>> rounder(3.5, 0.5)
    3.5
    

    这旨在在项目上多次调用它,通常在一些迭代的过程中。

    矢量化案例

    也可以重写它以便以矢量化方式工作:

    def rounder(x, y):
        r = x/y
        np.where(r-r//1 >= 0.5, y * np.ceil(r), y * np.floor(r))
    
    >>> rounder(np.array([2.1,2.2,3.6,3.5]), np.array([0.2, 0.2, 0.5, 0.5]))
    array([2.2, 2.2, 3.5, 3.5])
    

    【讨论】:

    • rounder(3.6, 0.5) 应该给我 4.0,根据你的功能它是 3.5。
    • 我在下面添加了解决方案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 1970-01-01
    • 2013-12-25
    相关资源
    最近更新 更多