Код пола / потолка все еще не работает должным образом - PullRequest
0 голосов
/ 21 февраля 2020

Через несколько недель go мне предоставили действительно полезный кусок кода, чтобы помочь мне округлить результаты моих данных о здоровье до 1 dp, используя принцип округления с 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.

1 Ответ

0 голосов
/ 21 февраля 2020

Вы, вероятно, сталкиваетесь с «полукруглым округлением» или «округлением банкиров». 51,25 округляется до 51,2, 51,35 округляется до 51,4. В вычислениях очень распространено предотвращение ошибок агрегации. Вы можете настроить это, хотя. См. Как правильно округлить половину числа с плавающей запятой в Python?

Кроме того, ваш код, скорее всего, не работает, так как требует точного равенства между числами с плавающей точкой для бита delta >= 0.5 работать, когда дельта точно 0,5. Деление на 10, вероятно, дает вам потерю точности, так что вы не можете впоследствии получить точное равенство.

Редактировать: Ваша проблема в том, что первоначальный расчет 82.0 / 160.0 * 100 дает вам ответ, который больше не точно 51.25 из-за потери точности из-за деления / умножения с плавающей точкой. Умножение первого так, что числа остаются целыми, поможет. Но на самом деле вам нужно использовать десятичный (https://docs.python.org/3/library/decimal.html) модуль, чтобы гарантировать, что арифметика с основанием десять c даст вам «естественные ответы».

...