首页 > 解决方案 > 地板/天花板代码仍然无法按要求工作

问题描述

几周前,我收到了一段非常有用的代码,可以帮助我将我的健康数据结果四舍五入到 1dp,使用舍入 1.25 到 1.3 的原则(Python 3 不这样做作为标准)。不幸的是,我遇到了一个我新定义的舍入规则不起作用的实例!有人可以建议修改下面的 my_round 吗?这太令人沮丧了,因为我以为我在这里找到了完美的解决方案。

import pandas as pd
import math
raw_data = {'AreaCode' : ['101', '101', '101'],
            'Disaggregation' : ['1864', '65Over', 'Total'],
            'Numerator' : [19.0, 82.0, 101.0],
            'Denominator' : [24.0, 160.0, 184.0]}

Data = pd.DataFrame(raw_data, columns = ['AreaCode', 'Disaggregation', 'Numerator', 'Denominator'])

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

Data['Outcome'] = (Data['Numerator'] / (Data['Denominator'])*100).apply(my_round)

运行所有这些时,您可以看到 65Over 结果已舍入为 51.2,而计算结果为 82.0 / 160.0 * 100 = 51.250000。我必须确定这些实例会在我发布的数据中输出为 51.3。

标签: roundingfloorceil

解决方案


您可能会遇到“半偶数舍入”或“银行家舍入”。51.25 将四舍五入为 51.2,51.35 将四舍五入为 51.4。在计算中防止聚合错误是很常见的。不过,您可以自定义它。请参阅如何在 Python 中正确舍入半浮点数?

此外,您的代码可能无法正常工作,因为delta >= 0.5当 delta 正好为 0.5 时,它需要浮点数之间完全相等才能使该位工作。除以 10 可能会使您失去精度,因此您随后无法获得完全相等的结果。

82.0 / 160.0 * 100编辑:您的问题是,由于浮点除法/乘法导致精度损失,原始计算给出的答案不再是 51.25。首先乘以使数字保持整数会有所帮助。但实际上,您需要使用 Decimal ( https://docs.python.org/3/library/decimal.html ) 模块来确保以十为底的算术为您提供“自然答案”。


推荐阅读