J'ai découvert l'opérateur //
dans Python qui, en Python 3, divise avec floor.
Y at-il un opérateur qui divise avec ceil à la place? (Je connais l'opérateur /
qui, dans Python 3, effectue la division en virgule flottante.)
Il n'y a pas d'opérateur qui divise avec ceil. Vous devez import math
et utiliser math.ceil
Vous pouvez simplement faire la division du plancher à l'envers:
def ceildiv(a, b):
return -(-a // b)
Cela fonctionne car L'opérateur de division de Python effectue la division d'étage (contrairement à C, où la division entière tronque la partie décimale).
Cela fonctionne également avec les grands entiers de Python, car il n'y a pas de conversion (avec perte) en virgule flottante.
Voici une démonstration:
>>> 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]
Vous pouvez faire (x + (d-1)) // d
en divisant x
par d
, c.-à-d. (x + 4) // 5
.
Vous pouvez toujours le faire en ligne aussi bien
((foo - 1) // bar) + 1
En python3, cela n’est guère plus rapide que de forcer la division du flottant et d’appeler ceil (), à condition que vous vous préoccupiez de la vitesse. Ce que vous ne devriez pas, sauf si vous en avez fait la preuve par l'usage.
>>> timeit.timeit("((5 - 1) // 4) + 1", number = 100000000)
1.7249219375662506
>>> timeit.timeit("ceil(5/4)", setup="from math import ceil", number = 100000000)
12.096064013894647
Notez que math.ceil est limité à 53 bits de précision. Si vous travaillez avec des entiers de grande taille, vous risquez de ne pas obtenir des résultats exacts.
Le gmpy2 libary fournit une fonction c_div
qui utilise l’arrondi du plafond.
Disclaimer: Je maintiens gmpy2.
def ceiling_division(n, d):
return -(n // -d)
Réminiscence du astuce de lévitation Penn & Teller , cela "bouleverse le monde (avec négation), utilise la division du sol (où le plafond et le sol ont été permutés), puis le monde à droite up (avec la négation encore) "
def ceiling_division(n, d):
q, r = divmod(n, d)
return q + bool(r)
La fonction divmod () donne (a // b, a % b)
pour les entiers (cela peut être moins fiable avec les flottants en raison d'une erreur d'arrondi). Le pas avec bool(r)
ajoute un au quotient chaque fois qu'il reste un reste différent de zéro.
def ceiling_division(n, d):
return (n + d - 1) // d
Convertissez le numérateur vers le haut de manière à ce que la division du sol soit arrondie au plafond souhaité. Notez que cela ne fonctionne que pour les entiers.
def ceiling_division(n, d):
return math.ceil(n / d)
Le code math.ceil () est facile à comprendre, mais il convertit des ints en float et retour. Ce n'est pas très rapide et il peut y avoir des problèmes d'arrondi. En outre, il s’appuie sur la sémantique de Python 3 dans laquelle "true division" produit un float et où la fonction ceil () renvoie un entier.