Python rundet die Ganzzahl auf die nächsten hundert auf
78
Scheint, das hätte schon hunderte Male gefragt werden sollen (Wortspiel macht Spaß =), aber ich kann nur eine Funktion zum Runden von Schwimmern finden. Wie runde ich eine ganze Zahl auf, zum Beispiel : 130 -> 200?
Möchten Sie, dass 100 auch auf 200 aufgerundet werden?
DSM
Nein, Thomas 'Antwort macht genau das, was ich brauche
userBG
1
Thomas' Antwort hat rund 100 bis 200. Deshalb fragte ich.
DSM
Überprüfen Sie die Bearbeitung, das habe ich in der ersten Antwort nicht beachtet.
Thomas Orozco
1
@ofko: Sie haben eine Antwort akzeptiert, die mit großen Ganzzahlen fehlschlägt. Einzelheiten finden Sie in meiner aktualisierten Antwort.
John Machin
Antworten:
150
Das Runden erfolgt normalerweise mit Gleitkommazahlen. Hier sollten Sie drei grundlegende Funktionen kennen: round(auf die nächste Ganzzahl runden), math.floor(immer abrunden) und math.ceil(immer aufrunden).
Sie fragen nach ganzen Zahlen und runden auf Hunderte auf, aber wir können immer noch verwenden math.ceil, solange Ihre Zahlen kleiner als 2 53 sind . Zur Verwendung math.ceilteilen wir einfach zuerst durch 100, runden auf und multiplizieren danach mit 100:
Wenn Sie zuerst durch 100 dividieren und anschließend mit 100 multiplizieren, werden zwei Dezimalstellen nach rechts und links verschoben, sodass math.ceilHunderte funktionieren. Sie können 10**nanstelle von 100 auch verwenden, wenn Sie auf Zehner ( n = 1), Tausender ( n = 3) usw. runden möchten .
Eine alternative Möglichkeit besteht darin, Gleitkommazahlen zu vermeiden (sie haben eine begrenzte Genauigkeit) und stattdessen nur Ganzzahlen zu verwenden. Ganzzahlen haben in Python eine beliebige Genauigkeit, sodass Sie Zahlen beliebiger Größe runden können. Die Regel für das Runden ist einfach: Finden Sie den Rest nach der Division mit 100 und addieren Sie 100 minus diesen Rest, wenn er nicht Null ist:
>>> defroundup(x):... return x if x % 100 == 0else x + 100 - x % 100
Ich habe einen Mini-Benchmark der beiden Lösungen durchgeführt:
$ python -m timeit -s 'import math' -s 'x = 130''int(math.ceil(x/100.0)) * 100'1000000 loops, best of 3: 0.364 usec per loop
$ python -m timeit -s 'x = 130''x if x % 100 == 0 else x + 100 - x % 100'10000000 loops, best of 3: 0.162 usec per loop
Die reine ganzzahlige Lösung ist im Vergleich zur math.ceilLösung um den Faktor zwei schneller .
Thomas schlug eine ganzzahlige Lösung vor, die mit der oben beschriebenen identisch ist, außer dass sie einen Trick durch Multiplizieren von Booleschen Werten verwendet. Es ist interessant zu sehen, dass es keinen Geschwindigkeitsvorteil gibt, den Code so zu schreiben:
$ python -m timeit -s 'x = 130''x + 100*(x%100>0) - x%100'10000000 loops, best of 3: 0.167 usec per loop
Lassen Sie mich abschließend noch bemerken, dass die eingebaute Funktion dies für Sie tun kann , wenn Sie 101–149 auf 100 und 150–199 auf 200 runden wollten, z. B. auf die nächsten hundert runden möchten round:
Ich mache hier keine normale Rundung, wenn ich ja wäre, würde ich round ()
userBG
3
@ofko: Richtig, du willst abrunden. Dies math.ceilist der kanonische Weg, dies zu tun - Teilen und Multiplizieren mit 100 ist der kanonische Weg round,ceil und die floorArbeit an Hunderten.
Martin Geisler
1
Nach den letzten Änderungen ist es jetzt sinnvoll, diese Antwort zu akzeptieren.
UserBG
2
-1 Dieser Ansatz mag bei Floats "kanonisch" sein, schlägt jedoch bei großen ganzen Zahlen fehl . Siehe meine Antwort für Details. Das OP fragte speziell nach ganzen Zahlen und drückte keine Obergrenze für die Größe der Zahlen aus.
John Machin
1
@ JohnMachin: Die Abwertung bezieht sich auf Fragen, die "nicht nützlich" sind, und ich verstehe nicht, warum diese einfache und direkte Antwort nicht nützlich ist. Infact, markiert die OP als angenommen, so dass es ist nützlich. Wenn jemand Hilfe braucht, um 130 bis 200 zu runden, dann ist es meiner Meinung nach etwas anstrengend, sich darüber zu beschweren, dass 1234567891234567891 nicht richtig gerundet wird. Sie haben Recht, dass es im floatVergleich zu long(natürlich!) Eine begrenzte Präzision gibt , aber für die meisten praktischen Situationen floatist a ziemlich groß.
Martin Geisler
26
Dies ist eine späte Antwort, aber es gibt eine einfache Lösung, die die besten Aspekte der vorhandenen Antworten kombiniert: Das nächste Vielfache von 100bis xist x - x % -100(oder wenn Sie es vorziehen x + (-x) % 100).
>>> x = 130>>> x -= x % -100# Round x up to next multiple of 100.>>> x
200
Dies ist schnell und einfach, liefert korrekte Ergebnisse für jede ganze Zahl x(wie die Antwort von John Machin) und liefert auch vernünftige Ergebnisse (modulo die üblichen Vorbehalte bezüglich der Gleitkommadarstellung), wenn xes sich um ein Gleitkomma handelt (wie die Antwort von Martin Geisler).
Ihre Lösung ist so schnell wie die von Martin, aber die Notation ist kürzer. Vielen Dank. % timeit 'x = 110' 'x - = x% -100' # 100000000 Schleifen, am besten 3: 9,37 ns pro Schleife VS% timeit 'x = 110' 'x + 100 * (x% 100> 0) - x % 100 '# 100000000 Schleifen, am besten 3: 9,38 ns pro Schleife
Für anicht negativ, bpositiv, beide ganzen Zahlen:
>>> rup = lambda a, b: (a + b - 1) // b * b
>>> [(x, rup(x, 100)) for x in (199, 200, 201)]
[(199, 200), (200, 200), (201, 300)]
Aktualisieren Die aktuell akzeptierte Antwort fällt mit ganzen Zahlen auseinander, sodass float (x) / float (y) nicht genau als a dargestellt werden kann float. Siehe diesen Code:
import math
defgeisler(x, y):returnint(math.ceil(x / float(y))) * y
deforozco(x, y):return x + y * (x % y > 0) - x % y
defmachin(x, y):return (x + y - 1) // y * y
for m, n in (
(123456789123456789, 100),
(1234567891234567891, 100),
(12345678912345678912, 100),
):
print; print m, "m"; print n, "n"for func in (geissler, orozco, machin):
print func(m, n), func.__name__
Ausgabe:
123456789123456789 m
100 n
123456789123456800 geisler
123456789123456800 orozco
123456789123456800 machin
1234567891234567891 m
100 n
1234567891234568000 geisler <<<=== wrong
1234567891234567900 orozco
1234567891234567900 machin
12345678912345678912 m
100 n
12345678912345680000 geisler <<<=== wrong
12345678912345679000 orozco
12345678912345679000 machin
Und hier sind einige Timings:
>\python27\python -m timeit -s "import math;x =130""int(math.ceil(x/100.0))*100"1000000 loops, best of 3: 0.342 usec per loop
>\python27\python -m timeit -s "x = 130""x + 100 * (x % 100 > 0) - x % 100"10000000 loops, best of 3: 0.151 usec per loop
>\python27\python -m timeit -s "x = 100""(x + 99) // 100 * 100"10000000 loops, best of 3: 0.0903 usec per loop
I know the OP was about rounding an integer- aber ich wollte darauf hinweisen, dass Sie versuchen würden, diese 3 Optionen für (0.5,10) zu verwenden, von denen ich erwarten würde, dass sie 10 zurückgeben, dann geben die ersten beiden Methoden (geisler & orozco) wie erwartet 10 zurück, während
machin
3
Wenn Ihr int x ist: x + 100 - x % 100
Wie in den Kommentaren angegeben, gibt dies jedoch 200 zurück, wenn x==100.
Wenn dies nicht das erwartete Verhalten ist, können Sie verwenden x + 100*(x%100>0) - x%100
Vielleicht möchten Sie die anderen Lösungen verwenden, wenn Sie keine magischen Zahlen mögen. Wenn Sie sich mit der Leistung befassen, läuft dies jedoch schneller.
Thomas Orozco
Ja, 100 sollte nicht aufgerundet bleiben, aber wenn das die Formel zu kompliziert machen würde, kann ich verhindern, dass Code verwendet wird, kein Problem
userBG
Nun, die andere Version löst dieses Problem, da sie die Prüfung vor dem Hinzufügen von 100 enthält! Wenn dies Ihren Bedürfnissen entspricht, vergessen Sie nicht zu akzeptieren! :)
Thomas Orozco
1
Es tut mir leid, aber ich finde diesen Code sehr unpythonisch. Ja, a boolhat einen numerischen Wert, also können Sie mit einem booleschen Ausdruck multiplizieren. Die anderen Lösungen sind jedoch klarer.
Martin Geisler
Nun, ich habe in der Tat darauf hingewiesen, dass anderer Code bevorzugt werden könnte, wenn die Leistung kein Schlüsselparameter ist.
Thomas Orozco
3
Versuche dies:
import math
defceilm(number,multiple):'''Returns a float rounded up by a factor of the multiple specified'''return math.ceil(float(number)/multiple)*multiple
Da so viele der Antworten hier den Zeitpunkt dafür bestimmen, wollte ich eine weitere Alternative hinzufügen.
Nehmen Sie @Martin Geislers
defroundup(x):return x if x % 100 == 0else x + 100 - x % 100
(was mir aus mehreren Gründen am besten gefällt)
aber die% Aktion herausrechnen
defroundup2(x):
x100= x % 100return x if x100 == 0else x + 100 - x100
Ergibt eine Geschwindigkeitsverbesserung von ~ 20% gegenüber dem Original
defroundup3(x):
x100 = x % 100return x ifnot x100 else x + 100 - x100
Ist noch besser und ~ 36% schneller als das Original
Schließlich dachte ich, ich könnte den notOperator fallen lassen und die Reihenfolge der Zweige ändern, in der Hoffnung, dass dies auch die Geschwindigkeit erhöhen würde, war aber verblüfft, als ich herausfand, dass es tatsächlich langsamer ist, zurückzufallen und nur 23% schneller als das Original zu sein.
defroundup4(x):
x100 = x % 100return x + 100 - x100 if x100 else x
>python -m timeit -s "x = 130""x if x % 100 == 0 else x + 100 - x % 100"1000000 loops, best of 3: 0.359 usec per loop
>python -m timeit -s "x = 130""x100 = x % 100""x if x100 == 0 else x + 100 - x100"1000000 loops, best of 3: 0.287 usec per loop
>python -m timeit -s "x = 130""x100 = x % 100""x if not x100 else x + 100 - x100"1000000 loops, best of 3: 0.23 usec per loop
>python -m timeit -s "x = 130""x100 = x % 100""x + 100 - x100 if x100 else x"1000000 loops, best of 3: 0.277 usec per loop
Erklärungen, warum 3 schneller ist als 4, wären sehr willkommen.
Führen Sie die ganzzahlige Division durch 100 durch (sie schneidet im Grunde den Bruchteil der normalen Division ab). Auf diese Weise erhalten Sie die Zehnerzahl. Zum Beispiel: 243 // 100 = 2.
Mit 100 multiplizieren, um die ursprüngliche Zahl ohne Zehner und Einsen zu erhalten. Zum Beispiel: 2 * 100 = 200.
Addiere 100, um das gewünschte Ergebnis zu erhalten. Zum Beispiel: 200 + 100 = 300
Einige Beispiele
0 ... 99 auf 100 gerundet
100 ... 199 auf 200 gerundet
usw.
Ein leicht modifizierter Ansatz rundet 1 ... 100 bis 100, 101 ... 200 bis 200 usw.:
Antworten:
Das Runden erfolgt normalerweise mit Gleitkommazahlen. Hier sollten Sie drei grundlegende Funktionen kennen:
round
(auf die nächste Ganzzahl runden),math.floor
(immer abrunden) undmath.ceil
(immer aufrunden).Sie fragen nach ganzen Zahlen und runden auf Hunderte auf, aber wir können immer noch verwenden
math.ceil
, solange Ihre Zahlen kleiner als 2 53 sind . Zur Verwendungmath.ceil
teilen wir einfach zuerst durch 100, runden auf und multiplizieren danach mit 100:>>> import math >>> def roundup(x): ... return int(math.ceil(x / 100.0)) * 100 ... >>> roundup(100) 100 >>> roundup(101) 200
Wenn Sie zuerst durch 100 dividieren und anschließend mit 100 multiplizieren, werden zwei Dezimalstellen nach rechts und links verschoben, sodass
math.ceil
Hunderte funktionieren. Sie können10**n
anstelle von 100 auch verwenden, wenn Sie auf Zehner (n = 1
), Tausender (n = 3
) usw. runden möchten .Eine alternative Möglichkeit besteht darin, Gleitkommazahlen zu vermeiden (sie haben eine begrenzte Genauigkeit) und stattdessen nur Ganzzahlen zu verwenden. Ganzzahlen haben in Python eine beliebige Genauigkeit, sodass Sie Zahlen beliebiger Größe runden können. Die Regel für das Runden ist einfach: Finden Sie den Rest nach der Division mit 100 und addieren Sie 100 minus diesen Rest, wenn er nicht Null ist:
>>> def roundup(x): ... return x if x % 100 == 0 else x + 100 - x % 100
Dies funktioniert für Zahlen jeder Größe:
>>> roundup(100) 100 >>> roundup(130) 200 >>> roundup(1234567891234567891) 1234567891234567900L
Ich habe einen Mini-Benchmark der beiden Lösungen durchgeführt:
$ python -m timeit -s 'import math' -s 'x = 130' 'int(math.ceil(x/100.0)) * 100' 1000000 loops, best of 3: 0.364 usec per loop $ python -m timeit -s 'x = 130' 'x if x % 100 == 0 else x + 100 - x % 100' 10000000 loops, best of 3: 0.162 usec per loop
Die reine ganzzahlige Lösung ist im Vergleich zur
math.ceil
Lösung um den Faktor zwei schneller .Thomas schlug eine ganzzahlige Lösung vor, die mit der oben beschriebenen identisch ist, außer dass sie einen Trick durch Multiplizieren von Booleschen Werten verwendet. Es ist interessant zu sehen, dass es keinen Geschwindigkeitsvorteil gibt, den Code so zu schreiben:
$ python -m timeit -s 'x = 130' 'x + 100*(x%100>0) - x%100' 10000000 loops, best of 3: 0.167 usec per loop
Lassen Sie mich abschließend noch bemerken, dass die eingebaute Funktion dies für Sie tun kann , wenn Sie 101–149 auf 100 und 150–199 auf 200 runden wollten, z. B. auf die nächsten hundert runden möchten
round
:>>> int(round(130, -2)) 100 >>> int(round(170, -2)) 200
quelle
math.ceil
ist der kanonische Weg, dies zu tun - Teilen und Multiplizieren mit 100 ist der kanonische Weground
,ceil
und diefloor
Arbeit an Hunderten.float
Vergleich zulong
(natürlich!) Eine begrenzte Präzision gibt , aber für die meisten praktischen Situationenfloat
ist a ziemlich groß.Dies ist eine späte Antwort, aber es gibt eine einfache Lösung, die die besten Aspekte der vorhandenen Antworten kombiniert: Das nächste Vielfache von
100
bisx
istx - x % -100
(oder wenn Sie es vorziehenx + (-x) % 100
).>>> x = 130 >>> x -= x % -100 # Round x up to next multiple of 100. >>> x 200
Dies ist schnell und einfach, liefert korrekte Ergebnisse für jede ganze Zahl
x
(wie die Antwort von John Machin) und liefert auch vernünftige Ergebnisse (modulo die üblichen Vorbehalte bezüglich der Gleitkommadarstellung), wennx
es sich um ein Gleitkomma handelt (wie die Antwort von Martin Geisler).>>> x = 0.1 >>> x -= x % -100 >>> x 100.0
quelle
Versuche dies:
int(round(130 + 49, -2))
quelle
Hier ist eine allgemeine Methode zum Aufrunden auf das nächste Vielfache einer positiven Ganzzahl:
def roundUpToMultiple(number, multiple): num = number + (multiple - 1) return num - (num % multiple)
Beispielnutzung:
quelle
lambda number, multiple: multiple * (1 + (number - 1) // multiple)
Für
a
nicht negativ,b
positiv, beide ganzen Zahlen:>>> rup = lambda a, b: (a + b - 1) // b * b >>> [(x, rup(x, 100)) for x in (199, 200, 201)] [(199, 200), (200, 200), (201, 300)]
Aktualisieren Die aktuell akzeptierte Antwort fällt mit ganzen Zahlen auseinander, sodass float (x) / float (y) nicht genau als a dargestellt werden kann
float
. Siehe diesen Code:import math def geisler(x, y): return int(math.ceil(x / float(y))) * y def orozco(x, y): return x + y * (x % y > 0) - x % y def machin(x, y): return (x + y - 1) // y * y for m, n in ( (123456789123456789, 100), (1234567891234567891, 100), (12345678912345678912, 100), ): print; print m, "m"; print n, "n" for func in (geissler, orozco, machin): print func(m, n), func.__name__
Ausgabe:
123456789123456789 m 100 n 123456789123456800 geisler 123456789123456800 orozco 123456789123456800 machin 1234567891234567891 m 100 n 1234567891234568000 geisler <<<=== wrong 1234567891234567900 orozco 1234567891234567900 machin 12345678912345678912 m 100 n 12345678912345680000 geisler <<<=== wrong 12345678912345679000 orozco 12345678912345679000 machin
Und hier sind einige Timings:
>\python27\python -m timeit -s "import math;x =130" "int(math.ceil(x/100.0))*100" 1000000 loops, best of 3: 0.342 usec per loop >\python27\python -m timeit -s "x = 130" "x + 100 * (x % 100 > 0) - x % 100" 10000000 loops, best of 3: 0.151 usec per loop >\python27\python -m timeit -s "x = 100" "(x + 99) // 100 * 100" 10000000 loops, best of 3: 0.0903 usec per loop
quelle
I know the OP was about rounding an integer
- aber ich wollte darauf hinweisen, dass Sie versuchen würden, diese 3 Optionen für (0.5,10) zu verwenden, von denen ich erwarten würde, dass sie 10 zurückgeben, dann geben die ersten beiden Methoden (geisler & orozco) wie erwartet 10 zurück, währendWenn Ihr int x ist:
x + 100 - x % 100
Wie in den Kommentaren angegeben, gibt dies jedoch 200 zurück, wenn
x==100
.Wenn dies nicht das erwartete Verhalten ist, können Sie verwenden
x + 100*(x%100>0) - x%100
quelle
bool
hat einen numerischen Wert, also können Sie mit einem booleschen Ausdruck multiplizieren. Die anderen Lösungen sind jedoch klarer.Versuche dies:
import math def ceilm(number,multiple): '''Returns a float rounded up by a factor of the multiple specified''' return math.ceil(float(number)/multiple)*multiple
Beispielnutzung:
>>> ceilm(257,5) 260 >>> ceilm(260,5) 260
quelle
Warnung: Vorzeitige Optimierungen voraus ...
Da so viele der Antworten hier den Zeitpunkt dafür bestimmen, wollte ich eine weitere Alternative hinzufügen.
Nehmen Sie @Martin Geislers
def roundup(x): return x if x % 100 == 0 else x + 100 - x % 100
(was mir aus mehreren Gründen am besten gefällt)
aber die% Aktion herausrechnen
def roundup2(x): x100= x % 100 return x if x100 == 0 else x + 100 - x100
Ergibt eine Geschwindigkeitsverbesserung von ~ 20% gegenüber dem Original
def roundup3(x): x100 = x % 100 return x if not x100 else x + 100 - x100
Ist noch besser und ~ 36% schneller als das Original
Schließlich dachte ich, ich könnte den
not
Operator fallen lassen und die Reihenfolge der Zweige ändern, in der Hoffnung, dass dies auch die Geschwindigkeit erhöhen würde, war aber verblüfft, als ich herausfand, dass es tatsächlich langsamer ist, zurückzufallen und nur 23% schneller als das Original zu sein.def roundup4(x): x100 = x % 100 return x + 100 - x100 if x100 else x >python -m timeit -s "x = 130" "x if x % 100 == 0 else x + 100 - x % 100" 1000000 loops, best of 3: 0.359 usec per loop >python -m timeit -s "x = 130" "x100 = x % 100" "x if x100 == 0 else x + 100 - x100" 1000000 loops, best of 3: 0.287 usec per loop >python -m timeit -s "x = 130" "x100 = x % 100" "x if not x100 else x + 100 - x100" 1000000 loops, best of 3: 0.23 usec per loop >python -m timeit -s "x = 130" "x100 = x % 100" "x + 100 - x100 if x100 else x" 1000000 loops, best of 3: 0.277 usec per loop
Erklärungen, warum 3 schneller ist als 4, wären sehr willkommen.
quelle
Hier ist eine sehr einfache Lösung:
next_hundred = x//100*100+100
Wie funktioniert es?
Einige Beispiele
Ein leicht modifizierter Ansatz rundet 1 ... 100 bis 100, 101 ... 200 bis 200 usw.:
next_hundred = (x-1)//100*100+100
quelle