Home > Mobile >  None of the decimal rounding methods I know worked for my current need (converting string from a fra
None of the decimal rounding methods I know worked for my current need (converting string from a fra

Time:05-05

The values in the a list are the math division values that come from the API.

To convert a string into a calculation, I use eval().

The values in correct_list are the final results of this division add 1.
The API indicates this are the exact results of this calculation to work with its data.

But I'm having difficulties when these divisions have several decimal, each model I tried to format so that the limit of decimals was 2, the created list doesn't match perfectly with the correct result:

import math
import decimal
decimal.getcontext().rounding = decimal.ROUND_CEILING

def main():
    a = ['11/10', '29/20', '5/4', '1/2', '10/11', '2/1', '4/7', '11/8', '13/10', '1/8', '4/11', '5/4', '163/100', '11/20', '17/20', '23/20', '6/4', '1/1', '8/5']
    b = []
    correct_list = ['2.10', '2.45', '2.25', '1.50', '1.91', '3.00', '1.57', '2.38', '2.30', '1.13', '1.36', '2.25', '2.63', '1.55', '1.85', '2.15', '2.50', '2.00', '2.60']
    for c in a:
        b.append(f'{round(eval(c) 1, ndigits=2)}')
    print(b)
    if b == correct_list:
        print('Ok. Amazing Match!')

if __name__ == '__main__':
    main()

These were all my attempts:

b.append(f'{eval(c) 1:.2f}')
['2.10', '2.45', '2.25', '1.50', '1.91', '3.00', '1.57', '2.38', '2.30', '1.12', '1.36', '2.25', '2.63', '1.55', '1.85', '2.15', '2.50', '2.00', '2.60']
b.append(f'{math.ceil((eval(c) 1) * 100.0) / 100.0:.2f}')
['2.10', '2.46', '2.25', '1.50', '1.91', '3.00', '1.58', '2.38', '2.30', '1.13', '1.37', '2.25', '2.63', '1.55', '1.85', '2.15', '2.50', '2.00', '2.60']
b.append(f'{float(round(decimal.Decimal(str(eval(c) 1)), ndigits=2)):.2f}')
['2.10', '2.45', '2.25', '1.50', '1.91', '3.00', '1.58', '2.38', '2.30', '1.13', '1.37', '2.25', '2.63', '1.55', '1.85', '2.15', '2.50', '2.00', '2.60']
b.append(f'{round(eval(c) 1, ndigits=2):.2f}')
['2.10', '2.45', '2.25', '1.50', '1.91', '3.00', '1.57', '2.38', '2.30', '1.12', '1.36', '2.25', '2.63', '1.55', '1.85', '2.15', '2.50', '2.00', '2.60']

None delivered the results that perfectly match the API calculation model.

CodePudding user response:

The only case that the normal round() function doesn't handle the way you want is that it rounds 0.005 down to 0.00 instead of up to 0.01. So if you're willing to be cheesy, just add 1.001 instead of 1, and then use normal rounding.

a = ['11/10', '29/20', '5/4', '1/2', '10/11', '2/1', '4/7', '11/8', '13/10', '1/8', '4/11', '5/4', '163/100', '11/20', '17/20', '23/20', '6/4', '1/1', '8/5']
correct_list = ['2.10', '2.45', '2.25', '1.50', '1.91', '3.00', '1.57', '2.38', '2.30', '1.13', '1.36', '2.25', '2.63', '1.55', '1.85', '2.15', '2.50', '2.00', '2.60']
b = [f'{float.__truediv__(*map(float, c.split("/")))   1.001:.2f}' for c in a]
if b == correct_list:
    print('Ok. Amazing Match!')  # succeeds

If you want to use the decimal module to do it in a non-cheesy way, you need to do the math with Decimal objects, and the rounding method you want is ROUND_HALF_UP.

import decimal
decimal.getcontext().rounding = decimal.ROUND_HALF_UP

a = ['11/10', '29/20', '5/4', '1/2', '10/11', '2/1', '4/7', '11/8', '13/10', '1/8', '4/11', '5/4', '163/100', '11/20', '17/20', '23/20', '6/4', '1/1', '8/5']
correct_list = ['2.10', '2.45', '2.25', '1.50', '1.91', '3.00', '1.57', '2.38', '2.30', '1.13', '1.36', '2.25', '2.63', '1.55', '1.85', '2.15', '2.50', '2.00', '2.60']
b = []
for c in a:
    n, d = map(int, c.split("/"))
    result = decimal.Decimal(1)   decimal.Decimal(n) / decimal.Decimal(d)
    b.append(f'{result:.2f}')
if b == correct_list:
    print('Ok. Amazing Match!')  # succeeds

  • Related