【问题标题】:How to always round up a XX.5 in numpy如何始终在 numpy 中四舍五入 XX.5
【发布时间】:2019-04-11 14:11:45
【问题描述】:

我读到 numpy 在舍入方面是公正的,并且它的工作方式与其设计的方式相同。 “如果你总是将 0.5 舍入到下一个最大的数字,那么一堆舍入数字的平均值可能略大于未舍入数字的平均值:这种偏差或漂移会对某些数值算法和使它们不准确。”

忽略这些信息并假设我总是想四舍五入,我怎么能在 numpy 中做到这一点?假设我的数组可能很大。

为简单起见,假设我有数组:

import numpy as np

A = [ [10, 15, 30], [25, 134, 41], [134, 413, 51]]
A = np.array(A, dtype=np.int16)

decimal = A * .1
whole = np.round(decimal)

十进制看起来像:

[[  1.    1.5   3. ]
 [  2.5  13.4   4.1]
 [ 13.4  41.3   5.1]]

整体看起来像:

[[  1.   2.   3.]
 [  2.  13.   4.]
 [ 13.  41.   5.]]

如您所见,1.5 四舍五入为 2,2.5 也四舍五入为 2。我如何强制始终获得 XX.5 的向上取整答案?我知道我可以遍历数组并使用 python round() 但这肯定会慢得多。想知道是否有办法使用 numpy 函数来做到这一点

【问题讨论】:

  • 你希望负数有什么行为? -2.5 应该舍入到 -3.0 还是 -2.0?
  • 这是一个很好的问题,虽然在我的场景中没有负数所以我没有真正想到它

标签: python numpy rounding


【解决方案1】:

答案几乎永远不会是np.vectorize。您可以而且应该以完全矢量化的方式执行此操作。假设对于x >= 0,您需要r = floor(x + 0.5)。如果您希望负数向零舍入,同样的公式适用于x < 0。因此,假设您总是希望从零开始舍入。在这种情况下,您正在为x < 0 寻找ceil(x - 0.5)。

要在不调用np.vectorize 的情况下为整个数组实现这一点,您可以使用掩码:

def round_half_up(x):
    mask = (x >= 0)
    out = np.empty_like(x)
    out[mask] = np.floor(x[mask] + 0.5)
    out[~mask] = np.ceil(x[~mask] - 0.5)
    return out

请注意,如果您在一个方向上四舍五入,则不需要使用蒙版:

def round_up(x):
    return np.floor(x + 0.5)

现在,如果您想让它真正高效,您可以摆脱所有临时数组。这将使用 ufunc 的全部功能:

def round_half_up(x):
    out = x.copy()
    mask = (out >= 0)
    np.add(out, 0.5, where=mask, out=out)
    np.floor(out, where=mask, out=out)
    np.invert(mask, out=mask)
    np.subtract(out, 0.5, where=mask, out=out)
    np.ceil(out, where=mask, out=out)
    return out

还有:

def round_up(x):
    out = x + 0.5
    np.floor(out, out=out)
    return out

【讨论】:

    【解决方案2】:
    import numpy as np
    A = [ [1.0, 1.5, 3.0], [2.5, 13.4, 4.1], [13.4, 41.3, 5.1]]
    A = np.array(A)
    
    print(A)
    
    def rounder(x):
        if (x-int(x) >= 0.5):
            return np.ceil(x)
        else:
            return np.floor(x)
    
    rounder_vec = np.vectorize(rounder)
    whole = rounder_vec(A)
    print(whole)
    

    另外,您还可以查看numpy.ceil、numpy.floor、numpy.trunc 了解其他舍入样式

    【讨论】:

    • np.ceil 将始终将其四舍五入。我仍然希望 1.3 舍入到 1 和 1.5 舍入到 2。也许我的问题并不清楚,抱歉
    • 如果是这种情况,那么在 numpy.您可以做的是遍历每个元素并检查向上或向下舍入
    • 你真的不应该在 numpy 中循环。
    • 您的答案要求调用者在调用您的函数之前设置一个临时的 rounder_vec。这不是请求 - 请求将直接调用输入到输出
    猜你喜欢
    • 1970-01-01
    • 2023-01-12
    • 1970-01-01
    • 2022-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-04
    • 1970-01-01
    相关资源
    最近更新 更多