Runden Sie in Python auf 5 (oder eine andere Zahl)


162

Gibt es eine eingebaute Funktion, die wie folgt abrunden kann?

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

Antworten:


304

Ich kenne keine Standardfunktion in Python, aber das funktioniert bei mir:

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)

Es ist leicht zu verstehen, warum das oben genannte funktioniert. Sie möchten sicherstellen, dass Ihre durch 5 geteilte Zahl eine ganze Zahl ist, die korrekt gerundet ist. Also machen wir zuerst genau das ( round(float(x)/5)wo floates nur in Python2 benötigt wird) und da wir dann durch 5 teilen, multiplizieren wir auch mit 5. Die endgültige Konvertierung in interfolgt, weil round()in Python 2 ein Gleitkommawert zurückgegeben wird.

Ich habe die Funktion allgemeiner gestaltet, indem ich ihr einen baseParameter mit dem Standardwert 5 gegeben habe.


3
Wenn nur ganze Zahlen und Abrundungen, dann können Sie auch einfach tunx // base * base
Tjorriemorrie

7
Ich bin paranoid, aber ich bevorzuge es zu verwenden floor()und ceil()nicht zu base * floor(x/base)
gießen

1
@ user666412 math.floorund math.ceilerlauben keine Verwendung mit einer benutzerdefinierten Basis, daher ist die Einstellung irrelevant.
Acumenus

48

Zum Runden auf nicht ganzzahlige Werte wie 0,05:

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

Ich fand dies nützlich, da ich einfach in meinem Code suchen und ersetzen konnte, um "round (" in "myround (" zu ändern, ohne die Parameterwerte ändern zu müssen.


2
Sie können def my_round(x, prec=2, base=0.05): return (base * (np.array(x) / base).round()).round(prec) Folgendes verwenden: Dies akzeptiert auch Numpy-Arrays.
Saubhik

23

Es ist nur eine Frage der Skalierung

>>> 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

Das Entfernen des "Restes" würde funktionieren:

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

Wenn der Wert bereits eine Ganzzahl ist:

rounded = val - val % 5

Als eine Funktion:

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

Ich mag diese Antwort zum Runden auf den nächsten Bruchwert. dh wenn ich nur Inkremente von 0,25 will.
Jersey Bean


9

rund (x [, n]): Werte werden auf das nächste Vielfache von 10 zur Potenz minus n gerundet. Also wenn n negativ ist ...

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

Da 10 = 5 * 2 ist, können Sie die Ganzzahldivision und -multiplikation mit 2 anstelle der Gleitkommadivision und -multiplikation mit 5,0 verwenden. Nicht, dass das viel ausmacht, es sei denn, Sie mögen Bitverschiebungen

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

1
+1, um uns zu zeigen, dass round () Rundungen auf andere Vielfache als 1,0, einschließlich höherer Werte, verarbeiten kann. (Beachten Sie jedoch, dass der Bit-Shifting-Ansatz mit Floats nicht funktioniert, ganz zu schweigen davon, dass er für die meisten Programmierer viel weniger lesbar ist.)
Peter Hansen

1
@ Peter Hansen danke für die +1. Sie benötigen ein int (x), damit die Bitverschiebung mit Floats funktioniert. Einverstanden, nicht das am besten lesbare und ich würde es nicht selbst verwenden, aber ich mochte die "Reinheit" davon nur mit 1 und nicht 2 oder 5.
Pwdyson

6

Entschuldigung, ich wollte die Antwort von Alok Singhai kommentieren, aber es lässt mich nicht, weil ich keinen guten Ruf habe = /

Wie auch immer, wir können noch einen Schritt verallgemeinern und gehen:

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

Dies ermöglicht es uns, nicht ganzzahlige Basen wie .25jede andere gebrochene Basis zu verwenden.


Bitte versuchen Sie nicht, neue Benutzereinschränkungen zu umgehen, indem Sie einen Kommentar als Antwort veröffentlichen. Einschränkungen bestehen aus einem bestimmten Grund . Berücksichtigen Sie dies als möglichen Grund, warum und wie einige Antworten gelöscht werden.
Auf Wiedersehen StackExchange

4

Modifizierte Version von divround :-)

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

Verwenden Sie in diesem Fall Divround (Wert 5, 3)? oder vielleicht divround (Wert, 5, 2,5)?
Pwdyson

divround (Wert, 5, 3) genau.
Christian Hausknecht

4

Verwenden:

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

Es verwendet keine Multiplikation und konvertiert nicht von / nach Floats.

Rundung auf das nächste Vielfache von 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

Wie Sie sehen können, funktioniert es sowohl für negative als auch für positive Zahlen. Krawatten (zB -15 und 15) werden immer nach oben gerundet.

Ein ähnliches Beispiel, das auf das nächste Vielfache von 5 gerundet wird und zeigt, dass es sich auch für eine andere "Basis" wie erwartet verhält:

>>> 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

Falls jemand eine "finanzielle Rundung" benötigt (0,5 Runden immer auf):

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'))))

Gemäß Dokumentation sind andere Rundungsoptionen:

ROUND_CEILING (in Richtung Unendlichkeit),
ROUND_DOWN (in Richtung Null),
ROUND_FLOOR (in Richtung -Infinity),
ROUND_HALF_DOWN (zum nächsten mit Bindungen gegen Null),
ROUND_HALF_EVEN (zum nächsten mit Bindungen zum nächsten geraden Ganzzahl),
ROUND_HALF_UP (zum nächsten mit Bindungen) weg von Null) oder
ROUND_UP (weg von Null).
ROUND_05UP (von Null weg, wenn die letzte Ziffer nach dem Runden auf Null 0 oder 5 gewesen wäre; andernfalls gegen Null)

Standardmäßig verwendet Python ROUND_HALF_EVEN, da es einige statistische Vorteile bietet (die gerundeten Ergebnisse sind nicht verzerrt).


2

Für ganze Zahlen und mit Python 3:

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


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

Produzieren:

>>> [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

Nächstes Vielfaches von 5

Bedenken Sie, dass 51 in 55 konvertiert werden muss:

code here

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

1

Hier ist mein C-Code. Wenn ich es richtig verstehe, sollte es so etwas sein;

#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);
  }
}

und dies rundet auch auf das nächste Vielfache von 5, anstatt nur aufzurunden;

#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

Ein anderer Weg, dies zu tun (ohne explizite Multiplikations- oder Divisionsoperatoren):

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

-3

Sie können int()zum Abrunden „tricksen“ , anstatt abzurunden, indem Sie 0.5die Zahl addieren, an die Sie übergeben int().


2
Dies beantwortet nicht wirklich die Frage
Uri Agassi
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.