python: округление / форматирование с плавающей запятой / строка с заданным десятичным знаком / дробь - PullRequest
0 голосов
/ 06 июня 2018

Я нашел много сообщений, касающихся округления в python, но, насколько я понимаю, ни одна из них пока не решает мою проблему.

Два решения, которые я ищу:

  • Округление ближе всего: числа с плавающей запятой / строки, которые необходимо округлять по-разному в зависимости от их размера.

  • Округление вниз: числа с плавающей запятой / строки, которые необходимо округлить вниз по-разному в зависимости от их размера.

  • Округление: числа с плавающей запятой / строки, которые необходимо округлить вверх по-разному в зависимости от их размера.

Пример:

  • + 500: 0 десятичных знаков (целых чисел) (например, Ближайший: 500,5 -> 501; Вниз: 500,99 -> 500; Вверх: 500,01 -> 501)
  • + 100: 1 десятичные дроби (дробная часть: 0,2) (например, ближайший: 100,29 -> 100,2; пониженный: 100,39 -> 100,2; восходящий: 100,21 -> 100,4).Таким образом, значение должно заканчиваться на .0, .2, .4, .6 или .8
  • + 5: 2 десятичных знака (фракция: 0,01) (например, Ближайшее: 5,019 -> 5,02; Вниз: 5,019-> 5,01; Up: 5,011 -> 5,02).Таким образом, значение должно заканчиваться на .x0, .x1, .x2, .x3, .x4, .x5, .x6, .x7, .x8 или .x9

Результирующая переменная должна бытьстрока.

Интересная вещь, которую я ищу, - это функция, в которой я могу передать количество десятичных знаков и дробь

Ответы [ 2 ]

0 голосов
/ 06 июня 2018

Вы можете использовать Десятичный модуль для настраиваемых округлений :

import decimal 

def rnd(f,n,r=decimal.ROUND_HALF_DOWN):
    pat='1.'+'0'*n
    return str(decimal.Decimal(str(f)).quantize(decimal.Decimal(pat),r))

Теперь для проверки:

for n in (500.99,100.39,5.019):
    for i in (0,1,2):
        print('n={:10}, i={:2}, Down: {:>10}, Closest: {:>10}'.format(n,i, rnd(n,i,decimal.ROUND_FLOOR),rnd(n,i)))   

Отпечатки:

n=    500.99, i= 0, Down:        500, Closest:        501
n=    500.99, i= 1, Down:      500.9, Closest:      501.0
n=    500.99, i= 2, Down:     500.99, Closest:     500.99
n=    100.39, i= 0, Down:        100, Closest:        100
n=    100.39, i= 1, Down:      100.3, Closest:      100.4
n=    100.39, i= 2, Down:     100.39, Closest:     100.39
n=     5.019, i= 0, Down:          5, Closest:          5
n=     5.019, i= 1, Down:        5.0, Closest:        5.0
n=     5.019, i= 2, Down:       5.01, Closest:       5.02

(Примечание. Это разный выход в случае 1 десятичного знака и ввод 100.39. Пожалуйста, уточните желаемый вывод 100.2 в этом случае? Разве вывод не должен быть 100.3?)


С уточнением, я думаю, вам просто нужно использовать fmod:

import math 

def rnd(n,f,prec,direction='down'):
    if direction=='down':
        if prec==0:
            return str(int(n))
        return str(round(n-math.fmod(n,f),prec))
    else:
        if prec==0:
            return str(int(round(n)))
        n+=f
        return str(round(n-math.fmod(n,f),prec))

Работает со всеми приведенными примерами:

>>> rnd(500.99,0.1,0)
'500'
>>> rnd(500.99,0.1,0,'')
'501'
>>> rnd(100.39,0.2,1,'')
'100.4'
>>> rnd(100.39,0.2,1)
'100.2'
>>> rnd(100.59,0.2,1,'')
'100.6'
>>> rnd(100.59,0.2,1)
'100.4'
>>> rnd(5.019,0.01,2)
'5.01'
>>> rnd(5.019,0.01,2,'')
'5.02'

(Вызвать функцию с аргументом ключевого слова direction= с любым строковым значением, отличным от 'down', чтобы подняться. Измените по своему вкусу ...)


Редактировать 2

Возвращает метод, ближайший к введенному номеру:

def rnd(n,f,prec):
    n1=int(n) if prec==0 else round(n-math.fmod(n,f),prec)
    n2=float(int(round(n))) if prec==0 else round((n+f)-math.fmod((n+f),f),prec)
    return str(min((n1,n2), key=lambda e: math.fabs(e-n)))
0 голосов
/ 06 июня 2018

Как насчет этого?

def round_accordingly(num):

    if num>=500:
        return str(round(num))
    elif num>=100:
        return str(round(num, 1))
    elif num>=5:
        return str(round(num, 2))


print(round_accordingly(550.73424))
print(round_accordingly(200.234245))
print(round_accordingly(7.564743))
...