2012-01-14 1 views
43

Wygląda na to, że powinno się już zadać setki razy (kalambur jest zabawą =) razy, ale mogę znaleźć tylko funkcję zaokrąglania spławików. Jak zaokrąglić w górę liczbę całkowitą, na przykład: 130 -> 200?Python zaokrągla liczbę całkowitą do następnej setki

+0

Czy chcesz również zaokrąglić 100 do 200? – DSM

+0

Nie, odpowiedź Thomasa robi dokładnie to, czego potrzebuję. – ofko

+0

Odpowiedź Thomasa brzmi: od 100 do 200. Dlatego zapytałem. – DSM

Odpowiedz

78

Zaokrąglanie jest zazwyczaj wykonywane na liczbach zmiennoprzecinkowych, a tu są trzy podstawowe funkcje, które trzeba wiedzieć: round (zaokrągla do najbliższej liczby całkowitej), math.floor (zawsze zaokrągla w dół) i math.ceil (zawsze zaokrągla w górę).

Pytasz o liczby całkowite i zaokrąglając do setek, ale nadal możemy używać wartości math.ceil, o ile Twoje liczby są mniejsze niż 2 . Aby korzystać math.ceil, po prostu podzielić przez 100, po pierwsze, zaokrąglić w górę, i rozmnażajcie się z 100 potem:

>>> import math 
>>> def roundup(x): 
...  return int(math.ceil(x/100.0)) * 100 
... 
>>> roundup(100) 
100 
>>> roundup(101) 
200 

dzieląc przez 100 pierwszego i pomnożyć 100 później „przesuwa” dwa miejsca po przecinku na prawo i lewo, tak że math.ceil działa na setkach. Można użyć 10**n zamiast 100 jeśli chcesz zaokrąglić do kilkudziesięciu (n = 1), tysiące (n = 3) itp

Alternatywnym sposobem, aby to zrobić, aby uniknąć liczb zmiennoprzecinkowych (mają ograniczone precyzja) i zamiast używać tylko liczby całkowite. Liczby całkowite mają dowolną precyzję w Pythonie, więc pozwala to na zaokrąglanie liczb o dowolnym rozmiarze. Reguła dla zaokrąglenia jest prosta: znaleźć pozostałą po podziale z 100, i dodać 100 minus to reszta, jeśli jest różna od zera:

>>> def roundup(x): 
...  return x if x % 100 == 0 else x + 100 - x % 100 

To działa na liczbach dowolnej wielkości:

>>> roundup(100) 
100 
>>> roundup(130) 
200 
>>> roundup(1234567891234567891) 
1234567891234567900L 

I nie mini odniesienia dwóch roztworów:

$ 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 

czysty roztwór całkowita jest szybciej przez współczynnik dwa w stosunku do roztworu math.ceil.

Thomas zaproponował rozwiązanie oparte na liczbach całkowitych, które jest identyczne z tym, które mam powyżej, z tym wyjątkiem, że używa sztuczki przez pomnożenie wartości logicznych. Interesujące jest to, aby zobaczyć, że nie jest zaletą pisania kodu w ten sposób prędkość:

$ python -m timeit -s 'x = 130' 'x + 100*(x%100>0) - x%100' 
10000000 loops, best of 3: 0.167 usec per loop 

Jako ostatnia uwaga, pozwól mi również pamiętać, że jeśli chciał zaokrąglić 101-149 do 100 i okrągłym 150 -199 do 200, npOkrągłe do najbliższy stu, potem wbudowanej round funkcji może zrobić dla Ciebie:

>>> int(round(130, -2)) 
100 
>>> int(round(170, -2)) 
200 
+0

Nie robię tutaj normalnego zaokrąglenia, gdybym był tak, użyłbym round() – ofko

+3

@ofko: prawda, chcesz zaokrąglić w górę. "Math.ceil" jest kanonicznym sposobem na zrobienie tego - dzielenie i pomnażanie przez 100 jest kanonicznym sposobem na wykonanie "okrągłych", "ceilowych" i "podłogowych" na setkach. –

+1

Po ostatnich edycjach warto zaakceptować tę odpowiedź. – ofko

13

Spróbuj tego:

int(round(130 + 49, -2)) 
3

Jeśli int x: x + 100 - x % 100

Jednakże, jak zauważył w komentarzach, to powróci 200 jeśli x==100.

Jeśli nie jest to oczekiwane zachowanie, można użyć x + 100*(x%100>0) - x%100

+0

Co jeśli 'x' jest już wielokrotnością 100? –

+0

Możesz jednak użyć innych rozwiązań, jeśli nie lubisz magicznych liczb. Jeśli zależy Ci na wydajności, działa to jednak szybciej. –

+0

@LukeWoodward Świetny punkt, będę edytować –

17

Oto ogólny sposób zaokrąglania w górę do najbliższej wielokrotności każdej liczby całkowitej dodatniej:

def roundUpToMultiple(number, multiple): 
    num = number + (multiple - 1) 
    return num - (num % multiple) 
wykorzystanie

próbki:

 
>>> roundUpToMultiple(101, 100) 
200 
>>> roundUpToMultiple(654, 321) 
963 
+0

zbyt skomplikowana –

+0

odpowiednik, krótsza metoda: 'liczba lambda, wielokrotność: wielokrotność * (1 + (liczba - 1) // wielokrotność)' –

8

Na a nieujemnej, b położenie, tive, obie liczby całkowite:

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

AktualizacjaObecnie akceptowana odpowiedź rozpada całkowitymi tak, że pływak (x)/pływak (Y) nie może być dokładnie przedstawiony jako float. Zobacz ten kod:

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__ 

wyjścia:

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 

A oto kilka taktowania:

>\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 
+0

'Wiem, że OP dotyczył zaokrąglania liczby całkowitej' - ale chciałem zwrócić uwagę, że spróbowałbyś użyć tych 3 opcji na (0,5,10), które spodziewałbym się zwrócić 10, wtedy pierwsze dwie metody (geisler i orozco) zwracają 10 zgodnie z oczekiwaniami, podczas gdy machin zwraca 0 – epeleg

12

Jest to późna odpowiedź, ale nie jest to proste rozwiązanie, które łączy w sobie najlepsze aspekty istniejące odpowiedzi: następna wielokrotność 100 od x to x - x % -100 (lub jeśli wolisz, x + (-x) % 100).

>>> x = 130 
>>> x -= x % -100 # Round x up to next multiple of 100. 
>>> x 
200 

Jest to szybka i prosta, daje poprawne wyniki dla dowolnej liczby całkowitej x (jak odpowiedź John Machin) i również daje rozsądne-owski wyniki (modulo zwykłe ostrzeżenia odnośnie reprezentacji zmiennoprzecinkowej) jeżeli x to float (jak odpowiedź Martina Geislera).

>>> x = 0.1 
>>> x -= x % -100 
>>> x 
100.0 
+0

twoje rozwiązanie jest tak szybkie jak w przypadku Martina, ale notacja jest krótszy. dzięki. % timeit 'x = 110' 'x - = x% -100' # 100000000 pętli, najlepiej od 3: 9,37 ns na pętlę VS % timeit 'x = 110' 'x + 100 * (x% 100> 0) - x% 100 ' # 100000000 pętli, najlepiej 3: 9,38 ns na pętlę – tagoma

1

Spróbuj to: wykorzystanie

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 

próbki:

>>> ceilm(257,5) 
260 
>>> ceilm(260,5) 
260 
0

Warning: Wcześniaki optymalizacje przodzie ...

Ponieważ tak wiele odpowiedzi tutaj zrobić terminy to chciałem dodać kolejną alternatywę.

Biorąc @Martin Geisler jest

def roundup(x): 
    return x if x % 100 == 0 else x + 100 - x % 100 

(które najlepiej jak kilku powodów)

ale na czynniki na działanie%

def roundup2(x): 
    x100= x % 100 
    return x if x100 == 0 else x + 100 - x100 

daje poprawę szybkości około 20% w stosunku do oryginału:

def roundup3(x): 
    x100 = x % 100 
    return x if not x100 else x + 100 - x100 

Jest jeszcze lepszy i jest ~ 36% szybszy niż oryginalny

w końcu pomyślałem, że mogę zrzucić operatora not i zmienić kolejność oddziałów mając nadzieję, że to również zwiększy prędkość, ale był zaskoczony, aby dowiedzieć się, że w rzeczywistości powraca wolniej niż o 23% szybciej niż oryginał.

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 

wyjaśnienie, dlaczego 3 jest szybsze niż 4, byłoby bardzo mile widziane.