web-dev-qa-db-fra.com

Existe-t-il un équivalent plafond de // opérateur en Python?

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

78
Cradam

Il n'y a pas d'opérateur qui divise avec ceil. Vous devez import math et utiliser math.ceil

45
Charles Salvia

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]
225
dlitz

Vous pouvez faire (x + (d-1)) // d en divisant x par d, c.-à-d. (x + 4) // 5.

15
poke

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
13
Travis Griggs

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.

8
casevh

Solution 1: convertir le plancher au plafond avec négation

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

Solution 2: Laissez divmod () faire le travail

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.

Solution 3: ajustez le numérateur avant la division

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.

Solution 4: convertissez en float pour utiliser math.ceil ()

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.

1
Raymond Hettinger