web-dev-qa-db-fra.com

En Python, quel est le bon moyen d'arrondir vers zéro dans la division entière?

1/2

donne

0

comme il se doit. cependant,

-1/2

donne

-1

, mais je veux qu’il soit arrondi à 0 (c’est-à-dire que je veux que -1/2 soit 0), qu’il soit positif ou négatif. Quelle est la meilleure façon de le faire?

15
blacktrance

Ne division en virgule flottante puis convertir en un int. Aucun module supplémentaire nécessaire.

>>> int(float(-1)/2)
0
>>> int(float(-3)/2)
-1
>>> int(float(1)/2)
0
>>> int(float(3)/2)
1
13
Tim

La division par défaut des entiers de Python est de retourner la parole (vers l'infini négatif) sans possibilité de changer cela. Vous pouvez lisez la raison pour laquelle BDFL.

Pour faire la division "arrondie", vous utiliseriez:

>>> a=1
>>> b=2
>>> (a+(-a%b))//b
1
>>> a,b=-1,2
>>> (a+(-a%b))//b
0

Pour effectuer une troncature vers zéro et conserver une division entière, vous utilisez (a+(-a%b))//b si a ou b sont négatifs et la division par défaut si les deux sont positifs.

Cela fera la division entière et arrondira toujours vers zéro:

>>> a=1
>>> b=2
>>> a//b if a*b>0 else (a+(-a%b))//b
0
>>> a=-1
>>> b=2
>>> a//b if a*b>0 else (a+(-a%b))//b
0
>>> a,b=-3,2
>>> a//b if a*b>0 else (a+(-a%b))//b
-1
>>> a,b=3,2
>>> a//b if a*b>0 else (a+(-a%b))//b
1

note de bas de page

Curieusement, C99 déclare que arrondir à zéro est la valeur par défaut:

#include <stdio.h>
int main(int argc, const char * argv[])
{

    int a=-3;
    int b=2;
    printf("a=%d, b=%d, a/b=%d\n",a,b,a/b);
    a=3;
    printf("a=%d, b=%d, a/b=%d\n",a,b,a/b);
    return 0;
}

Impressions:

a=-3, b=2, a/b=-1
a=3, b=2, a/b=1
5
dawg

Pour ce que cela vaut, ma solution préférée est celle-ci. Calcul arithmétique entier uniquement, une division unique et tout le reste temps linéaire:

def integer_divide_towards_zero(a, b):
    return -(-a // b) if a < 0 else a // b

Cela suppose que b est positif, mais dans la plupart des applications que j'ai vues, c'est vrai. Si vous devez également traiter b négatif, la fonction devient légèrement plus compliquée:

def integer_divide_towards_zero(a, b):
    return -(-a // b) if (a < 0) ^ (b < 0) else a // b

Quelques exemples de sorties:

>>> integer_divide_towards_zero(11, 3)
3
>>> integer_divide_towards_zero(-11, 3)
-3
>>> integer_divide_towards_zero(6, 3)
2
>>> integer_divide_towards_zero(-6, 3)
-2
>>> integer_divide_towards_zero(11, -3)
-3
>>> integer_divide_towards_zero(-11, -3)
3
4
Mark Dickinson

Essaye ça. Ne fonctionne que pour les nombres supérieurs à -1

import math

x = .5
y = -.5

print math.floor(math.fabs(x))
>> 0

print math.floor(math.fabs(y))
>> 0
1
Conor Patrick

Jeter mon chapeau avec quelques idées alternatives:

Multipliez le signe du nombre [abs (x)/x] par les abs (x)/2

(abs(x)/x)*(abs(x)/2)

Effectuez l'addition, mais si le nombre est inférieur à zéro, ajoutez-en un pour le rapprocher de 0.

x/2 + int(x<0)
1
user764357

Le code correct pour le faire est, à mon avis, trop obscur pour écrire en 1 ligne. Donc, je le mettrais dans une fonction, comme:

def int0div(a, b):
    q = a // b
    if q < 0 and b*q != a:
        q += 1
    return q

Bonnes caractéristiques: cela fonctionne pour toutes les tailles d’int, ne modifie pas le résultat brut (a//b) sauf si nécessaire, ne fait qu’une division (% fait également une division sous les couvertures), et ne crée pas d’entiers plus grands que les entrées. Celles-ci peuvent ou non avoir de l'importance dans votre application; ils deviennent plus importants (pour la vitesse) si vous utilisez de "grands" entiers.

1
Tim Peters

Vous pouvez également utiliser le module Decimal dans les bibliothèques standard Python.

Plus précisément, "L’opérateur de division entière // se comporte de manière analogue, renvoyant la partie entière du quotient vrai (tronquant vers zéro) plutôt que son plancher, afin de conserver l’identité habituelle x == (x // y ) * y + x% y: "

>>> -7 // 4
-2
>>> Decimal(-7) // Decimal(4)
Decimal('-1')

Regardez aussi Modes d'arrondi car ils ont plusieurs façons de voir/arrondir vos informations - Plafond, bas, sol, moitié bas, moitié bas, moitié haut, et arrondi . 

Decimal a été écrit pour résoudre le problème traditionnel des mathématiques binaires dans un monde qui attend des solutions décimales.

0
jjisnow