Arrotonda a 5 (o altro numero) in Python


162

Esiste una funzione integrata che può arrotondare come la seguente?

10 -> 10
12 -> 10
13 -> 15
14 -> 15
16 -> 15
18 -> 20

Risposte:


304

Non conosco una funzione standard in Python, ma questo funziona per me:

Python 2

def myround(x, base=5):
    return int(base * round(float(x)/base))

python3

def myround(x, base=5):
    return base * round(x/base)

È facile capire perché funzioni sopra. Vuoi assicurarti che il tuo numero diviso per 5 sia un numero intero, arrotondato correttamente. Quindi, prima facciamo esattamente questo ( round(float(x)/5)dove floatè necessario solo in Python2), e poi, poiché abbiamo diviso per 5, moltipliciamo anche per 5. La conversione finale in intè perchéround() restituisce un valore in virgola mobile in Python 2.

Ho reso la funzione più generica assegnandole un baseparametro, il cui valore predefinito è 5.


3
Se solo numeri interi e arrotondamenti per difetto, allora puoi anche farex // base * base
Tjorriemorrie il

7
sono io che sono paranoico ma preferisco usare floor()e ceil()piuttosto che lanciare:base * floor(x/base)
user666412

1
@ user666412 math.floore math.ceilnon consentire l'utilizzo con una base personalizzata, quindi la preferenza è irrilevante.
Acumenus,

48

Per arrotondare a valori non interi, come 0,05:

def myround(x, prec=2, base=.05):
  return round(base * round(float(x)/base),prec)

L'ho trovato utile poiché potevo semplicemente fare una ricerca e sostituirlo nel mio codice per cambiare "round (" in "myround (", senza dover cambiare i valori dei parametri.


2
È possibile utilizzare: def my_round(x, prec=2, base=0.05): return (base * (np.array(x) / base).round()).round(prec) che accetta anche array intorpiditi.
saubhik,

23

È solo una questione di ridimensionamento

>>> a=[10,11,12,13,14,15,16,17,18,19,20]
>>> for b in a:
...     int(round(b/5.0)*5.0)
... 
10
10
10
15
15
15
15
15
20
20
20

14

Rimuovere il 'resto' funzionerebbe:

rounded = int(val) - int(val) % 5

Se il valore è areao un numero intero:

rounded = val - val % 5

Come una funzione:

def roundint(value, base=5):
    return int(value) - int(value) % int(base)

Mi piace questa risposta per arrotondare al valore frazionario più vicino. cioè se voglio solo incrementi di 0,25.
Fagiolo Jersey


9

round (x [, n]): i valori sono arrotondati al multiplo più vicino di 10 alla potenza meno n. Quindi se n è negativo ...

def round5(x):
    return int(round(x*2, -1)) / 2

Poiché 10 = 5 * 2, è possibile utilizzare la divisione e la moltiplicazione di numeri interi con 2, anziché la divisione e la moltiplicazione float con 5.0. Non è molto importante, a meno che non ti piaccia spostare un po '

def round5(x):
    return int(round(x << 1, -1)) >> 1

1
+1 per averci mostrato che round () può gestire l'arrotondamento per multipli diversi da 1.0, inclusi valori più alti. (Si noti, tuttavia, che l'approccio di spostamento dei bit non funziona con i float, per non parlare del fatto che è molto meno leggibile per la maggior parte dei programmatori.)
Peter Hansen

1
@Peter Hansen grazie per il +1. È necessario disporre di un int (x) affinché il bit shifting funzioni con i float. D'accordo non il più leggibile e non lo userei da solo, ma mi è piaciuta la "purezza" che coinvolge solo 1 e non 2 o 5.
pwdyson,

6

Mi dispiace, ho voluto commentare la risposta di Alok Singhai, ma non mi lascerà a causa della mancanza di reputazione = /

Ad ogni modo, possiamo generalizzare un altro passo e andare:

def myround(x, base=5):
    return base * round(float(x) / base)

Questo ci consente di utilizzare basi non intere, come .25o qualsiasi altra base frazionaria.


Non tentare di aggirare le restrizioni sui nuovi utenti pubblicando un commento come risposta. Le restrizioni esistono per un motivo . Tieni conto di questo come possibile motivo del perché e come vengono eliminate alcune risposte?
Arrivederci StackExchange il

4

Versione modificata di divround :-)

def divround(value, step, barrage):
    result, rest = divmod(value, step)
    return result*step if rest < barrage else (result+1)*step

quindi in questo caso usi divround (valore, 5, 3)? o forse divround (valore, 5, 2.5)?
pwdyson,

divround (valore, 5, 3), esattamente.
Christian Hausknecht,

4

Uso:

>>> def round_to_nearest(n, m):
        r = n % m
        return n + m - r if r + r >= m else n - r

Non utilizza la moltiplicazione e non converte da / a float.

Arrotondamento al multiplo più vicino di 10:

>>> for n in range(-21, 30, 3): print('{:3d}  =>  {:3d}'.format(n, round_to_nearest(n, 10)))
-21  =>  -20
-18  =>  -20
-15  =>  -10
-12  =>  -10
 -9  =>  -10
 -6  =>  -10
 -3  =>    0
  0  =>    0
  3  =>    0
  6  =>   10
  9  =>   10
 12  =>   10
 15  =>   20
 18  =>   20
 21  =>   20
 24  =>   20
 27  =>   30

Come puoi vedere, funziona sia con numeri negativi che positivi. I legami (ad es. -15 e 15) saranno sempre arrotondati verso l'alto.

Un esempio simile che viene arrotondato al multiplo più vicino di 5, dimostrando che si comporta anche come previsto per una "base" diversa:

>>> for n in range(-21, 30, 3): print('{:3d}  =>  {:3d}'.format(n, round_to_nearest(n, 5)))
-21  =>  -20
-18  =>  -20
-15  =>  -15
-12  =>  -10
 -9  =>  -10
 -6  =>   -5
 -3  =>   -5
  0  =>    0
  3  =>    5
  6  =>    5
  9  =>   10
 12  =>   10
 15  =>   15
 18  =>   20
 21  =>   20
 24  =>   25
 27  =>   25

2

Nel caso in cui qualcuno abbia bisogno di "arrotondamenti finanziari" (0,5 arrotondamenti sempre in alto):

def myround(x, base=5):
    roundcontext = decimal.Context(rounding=decimal.ROUND_HALF_UP)
    decimal.setcontext(roundcontext)
    return int(base *float(decimal.Decimal(x/base).quantize(decimal.Decimal('0'))))

Come da documentazione, altre opzioni di arrotondamento sono:

ROUND_CEILING (verso l'Infinito),
ROUND_DOWN (verso lo zero),
ROUND_FLOOR (verso -Infinito),
ROUND_HALF_DOWN (al più vicino con i legami che vanno verso lo zero),
ROUND_HALF_EVEN (al più vicino con i legami che vanno al più vicino pari intero),
ROUND_HALF_UP (al più vicino con legami in corso) lontano da zero) o
ROUND_UP (lontano da zero).
ROUND_05UP (lontano da zero se l'ultima cifra dopo l'arrotondamento verso zero sarebbe stata 0 o 5; altrimenti verso zero)

Per impostazione predefinita, Python utilizza ROUND_HALF_EVEN in quanto presenta alcuni vantaggi statistici (i risultati arrotondati non sono distorti).


2

Per numeri interi e con Python 3:

def divround_down(value, step):
    return value//step*step


def divround_up(value, step):
    return (value+step-1)//step*step

Produrre:

>>> [divround_down(x,5) for x in range(20)]
[0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 15, 15, 15, 15, 15]
>>> [divround_up(x,5) for x in range(20)]
[0, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 15, 15, 15, 15, 15, 20, 20, 20, 20]


1

Prossimo multiplo di 5

Considera 51 deve essere convertito in 55:

code here

mark = 51;
r = 100 - mark;
a = r%5;
new_mark = mark + a;

1

Ecco il mio codice C. Se lo capisco correttamente, dovrebbe essere qualcosa del genere;

#include <stdio.h>

int main(){
int number;

printf("Enter number: \n");
scanf("%d" , &number);

if(number%5 == 0)
    printf("It is multiple of 5\n");
else{
    while(number%5 != 0)
        number++;
  printf("%d\n",number);
  }
}

e questo arrotonda anche al multiplo più vicino di 5 invece di arrotondare per eccesso;

#include <stdio.h>

int main(){
int number;

printf("Enter number: \n");
scanf("%d" , &number);

if(number%5 == 0)
    printf("It is multiple of 5\n");
else{
    while(number%5 != 0)
        if (number%5 < 3)
            number--;
        else
        number++;
  printf("nearest multiple of 5 is: %d\n",number);
  }
}

1

Un altro modo per farlo (senza espliciti operatori di moltiplicazione o divisione):

def rnd(x, b=5):
    return round(x + min(-(x % b), b - (x % b), key=abs))

-3

Puoi "ingannare" int()per arrotondare invece di arrotondare per eccesso aggiungendo 0.5al numero a cui passi int().


2
Questo in realtà non risponde alla domanda
Uri Agassi,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.