2013-02-11 15 views
59

Ho scoperto l'operatore // in Python che in Python 3 esegue la divisione con floor.Esiste un equivalente soffitto di // operatore in Python?

C'è un operatore che divide invece con ceil? (Conosco l'operatore / che in Python 3 esegue la divisione in virgola mobile.)

+0

"divide-then-ceil" in realtà non è una cosa comune in matematica, mentre '' // si basa sul funzionamento integer divisione-con-modulo. – millimoose

+0

Importante: vuoi un risultato int o float? – smci

+3

È necessario modificare la risposta accettata a dlitz. math.ceil è per i float, non funziona con i long-in a precisione arbitraria di Python. – endolith

risposta

35

Non c'è un operatore che si divide con ceil. È necessario import math e utilizzare math.ceil

+0

quindi foobar = math.ceil (foo/bar)? Hmm, posso conviverci, non so dove volessi usarlo, era solo curioso, grazie – Cradam

+8

-1 ** non usare **, questo inizierà a fallire per interi molto grandi. Utilizzare una libreria aritmetica a precisione multipla o rimanere nel dominio intero con [questo] (https://stackoverflow.com/a/17511341/674039) approccio. – wim

9

si potrebbe fare (x + (d-1)) // d quando dividendo x da d, vale a dire (x + 4) // 5.

+0

Questo è il metodo classico che ho usato per sempre. Tuttavia, non funziona per i divisori negativi. –

+0

Produce lo [stesso risultato] (https://repl.it/FZGd/5) come 'math.ceil()'. – Abhijeet

+0

@Abhijeet Sì, è quello che chiede la domanda. Tranne che funziona meglio per i grandi numeri interi sopra 'sys.float_info.max', e non richiede un'importazione. – Artyer

8

È sempre possibile farlo solo in linea così

((foo - 1) // bar) + 1 

In python3, questo è solo timido di un ordine di grandezza più veloce di forzare la divisione del galleggiante e chiamando ceil(), purché vi preoccupate per la velocità . Che non dovresti, a meno che tu non abbia provato con l'uso di cui hai bisogno.

>>> timeit.timeit("((5 - 1) // 4) + 1", number = 100000000) 
1.7249219375662506 
>>> timeit.timeit("ceil(5/4)", setup="from math import ceil", number = 100000000) 
12.096064013894647 
+0

ho appena eseguito questi test io ottengo circa 12,5 secondi, ehrm, perché non mi interessa la velocità quando è una tale enorme differenza di velocità? – Cradam

+2

@Cradam Nota che sta usando 100 milioni di chiamate ('number = 100000000'). Per singola chiamata, la differenza è piuttosto insignificante. –

+0

ahh, grazie, userò il metodo ceil quindi – Cradam

7

Si noti che math.ceil è limitato a 53 bit di precisione. Se stai lavorando con numeri interi grandi, potresti non ottenere risultati esatti.

La libreria gmpy2 fornisce una funzione c_div che utilizza l'arrotondamento del soffitto.

Disclaimer: Gestisco gmpy2.

+2

Questo pacchetto sarebbe utile se stavo facendo qualcosa di pesantemente matematico o orientato alla scienza, preferisco la risposta che utilizza le librerie di base però. Sto dando un upvote però in quanto è una risposta utile – Cradam

163

si può solo fare capovolta divisione piano:

def ceildiv(a, b): 
    return -(-a // b) 

Questo funziona perché Python's division operator does floor division (a differenza di C, in cui divisione intera tronca la parte frazionaria).

Questo funziona anche con i grandi numeri interi di Python, poiché non vi è alcuna (perdita) conversione in virgola mobile.

Ecco una dimostrazione:

>>> from __future__ import division # a/b is float division 
>>> from math import ceil 
>>> b = 3 
>>> for a in range(-7, 8): 
...  print(["%d/%d" % (a, b), int(ceil(a/b)), -(-a // b)]) 
... 
['-7/3', -2, -2] 
['-6/3', -2, -2] 
['-5/3', -1, -1] 
['-4/3', -1, -1] 
['-3/3', -1, -1] 
['-2/3', 0, 0] 
['-1/3', 0, 0] 
['0/3', 0, 0] 
['1/3', 1, 1] 
['2/3', 1, 1] 
['3/3', 1, 1] 
['4/3', 2, 2] 
['5/3', 2, 2] 
['6/3', 2, 2] 
['7/3', 3, 3] 
+11

Wow! Molto intelligente! Questa dovrebbe essere la soluzione accettata. – apadana

Problemi correlati