Division Python

133

J'essayais de normaliser un ensemble de nombres de -100 à 0 dans une plage de 10 à 100 et j'avais des problèmes uniquement pour remarquer que même sans aucune variable, cela n'évalue pas la façon dont je m'attendais à ce qu'il le fasse:

>>> (20-10) / (100-10)
0

La division Float ne fonctionne pas non plus:

>>> float((20-10) / (100-10))
0.0

Si l'un des côtés de la division est jeté sur un flotteur, cela fonctionnera:

>>> (20-10) / float((100-10))
0.1111111111111111

Chaque côté du premier exemple est évalué comme un int, ce qui signifie que la réponse finale sera convertie en un int. Puisque 0,111 est inférieur à 0,5, il s'arrondit à 0. Ce n'est pas transparent à mon avis, mais je suppose que c'est ainsi.

Quelle est l'explication?

Adam Nelson
la source
3
Adam, je n'aime toujours pas votre explication. Le premier exemple est la division entière, qui renvoie simplement 0. Le deuxième exemple est mal mis entre parenthèses pour l'effet souhaité.
President James K. Polk
@GregS Le premier exemple était le problème. Le deuxième exemple est explicatif et a été rédigé après la première question. Toutes les réponses ci-dessous expliquent très bien le problème, en particulier celles de @KennyTM. Il est important de noter que mon problème d'origine n'est qu'un problème sur Python 2.x, pas 3. C'est un peu déconcertant que le comportement change comme ça mais maintenant que je sais, je vais utiliser de la future division d'importation et utiliser le 3 Comportement .x. À votre santé.
Adam Nelson
1
Adam, veuillez corriger votre dernière EDIT. Le côté droit n'a rien de spécial; pour qu'une division soit flottante, le numérateur ou le dénominateur (ou les deux) doit être flottant. Si vous pensez avoir lu dans la documentation que le côté droit doit être flottant, alors soit la documentation est mal formulée et devrait être corrigée, soit vous l'avez mal comprise. Avez-vous vu un exemple, peut-être, puis en avez-vous extrapolé une règle?
tzot le

Réponses:

246

Vous utilisez Python 2.x, où les divisions entières seront tronquées au lieu de devenir un nombre à virgule flottante.

>>> 1 / 2
0

Vous devriez en faire un float:

>>> float(10 - 20) / (100 - 10)
-0.1111111111111111

ou from __future__ import division, qui oblige /à adopter le comportement de Python 3.x qui renvoie toujours un float.

>>> from __future__ import division
>>> (10 - 20) / (100 - 10)
-0.1111111111111111
KennyTM
la source
10
Si vous utilisez, from __future__ import divisionvous pouvez obtenir l'ancien comportement de division de style C en utilisant deux barres obliques (par exemple, 1 // 2il en résultera 0). Voir Pep 238 Changer l'opérateur de division
Utilisateur
1
@User Pas besoin d'importer depuis __future__. Dans les deux Python, 2 et 3 font //référence __floordiv__()par défaut.
Casimir
21

Vous insérez des nombres entiers pour que Python vous renvoie un entier :

>>> 10 / 90
0

Si, par la suite, vous convertissez ceci en flottant, l'arrondi a déjà été effectué, en d'autres termes, 0 entier deviendra toujours 0 flottant.

Si vous utilisez des flotteurs de chaque côté de la division, Python vous donnera la réponse que vous attendez.

>>> 10 / 90.0
0.1111111111111111

Donc dans votre cas:

>>> float(20-10) / (100-10)
0.1111111111111111
>>> (20-10) / float(100-10)
0.1111111111111111
Dave Webb
la source
11

Vous devez le changer en flotteur AVANT de faire la division. C'est:

float(20 - 10) / (100 - 10)
A. Levy
la source
4
@Adam Nelson: Fonctionne correctement pour moi. Vérifiez vos parenthèses.
Fred Larson
En fait, je me trompe - mais après avoir regardé la documentation, il faut d'abord lancer le côté droit.
Adam Nelson
10
@Adam: Peu importe le côté en premier.
kennytm
11

En Python 2.7, l' /opérateur est une division entière si les entrées sont des entiers:

>>>20/15
1

>>>20.0/15.0
1.33333333333

>>>20.0/15
1.33333333333

En Python 3.3, l' /opérateur est une division flottante même si les entrées sont des nombres entiers.

>>> 20/15
1.33333333333

>>>20.0/15
1.33333333333

Pour la division entière dans Python 3, nous utiliserons l' //opérateur.

L' //opérateur est un opérateur de division entière dans Python 2.7 et Python 3.3.

Dans Python 2.7 et Python 3.3:

>>>20//15
1

Maintenant, voyez la comparaison

>>>a = 7.0/4.0
>>>b = 7/4
>>>print a == b

Pour le programme ci-dessus, la sortie sera False en Python 2.7 et True en Python 3.3.

En Python 2.7 a = 1.75 et b = 1.

En Python 3.3 a = 1.75 et b = 1.75, simplement parce que /c'est une division flottante.

Harsha Vardhan
la source
8

Cela a à voir avec la version de python que vous utilisez. Fondamentalement, il adopte le comportement C: si vous divisez deux entiers, les résultats seront arrondis à un entier inférieur. Gardez également à l'esprit que Python effectue les opérations de gauche à droite, ce qui joue un rôle lorsque vous tapez.

Exemple: Comme c'est une question qui me vient toujours à l'esprit lorsque je fais des opérations arithmétiques (dois-je convertir en float et quel nombre), un exemple de cet aspect est présenté:

>>> a = 1/2/3/4/5/4/3
>>> a
0

Lorsque nous divisons des nombres entiers, il n'est pas surprenant qu'il soit arrondi plus bas.

>>> a = 1/2/3/4/5/4/float(3)
>>> a
0.0

Si nous tapons le dernier entier à float, nous obtiendrons toujours zéro, car au moment où notre nombre est divisé par le flottant, il est déjà devenu 0 à cause de la division entière.

>>> a = 1/2/3/float(4)/5/4/3
>>> a
0.0

Même scénario que ci-dessus mais en déplaçant le type de flotteur un peu plus près du côté gauche.

>>> a = float(1)/2/3/4/5/4/3
>>> a
0.0006944444444444445

Enfin, lorsque nous tapons le premier entier à float, le résultat est celui souhaité, puisque à partir de la première division, c'est-à-dire la plus à gauche, nous utilisons des floats.

Extra 1: Si vous essayez de répondre à cela pour améliorer l'évaluation arithmétique, vous devriez vérifier ceci

Extra 2: veuillez faire attention au scénario suivant:

>>> a = float(1/2/3/4/5/4/3)
>>> a
0.0
George
la source
4

Spécifier un flotteur en plaçant un '.' après le nombre le fera également flotter par défaut.

>>> 1 / 2
0

>>> 1. / 2.
0.5
billmanH
la source
2

Faites au moins l'un d'eux flottant, alors ce sera une division flottante, pas un entier:

>>> (20.0-10) / (100-10)
0.1111111111111111

Lancer le résultat pour flotter est trop tard.

unbeli
la source
1

En python cv2pas mis à jour le calcul de la division. donc, vous devez inclure from __future__ import division dans la première ligne du programme.

Kavitha Raj
la source
0

Dans tous les cas, c'est une division entière. 10/90 = 0. Dans le second cas, vous lancez simplement 0 en float.

Essayez de convertir l'un des opérandes de "/" en flottant:

float(20-10) / (100-10)
Fred Larson
la source
0

Vous lancez pour flotter après que la division s'est déjà produite dans votre deuxième exemple. Essaye ça:

float(20-10) / float(100-10)
David M
la source
0

Je suis quelque peu surpris que personne n'ait mentionné que l'affiche originale aurait pu aimer les nombres rationnels . Si cela vous intéresse, le programme Sage basé sur Python vous soutient . (Actuellement toujours basé sur Python 2.x, bien que 3.x soit en cours.)

sage: (20-10) / (100-10)
1/9

Ce n'est pas une solution pour tout le monde, car il fait un préparage donc ces nombres ne sont pas des ints, mais Integerdes éléments de classe Sage . Néanmoins, il convient de mentionner dans le cadre de l'écosystème Python.

kcrisman
la source
0

Personnellement, j'ai préféré insérer un 1. *au tout début. Donc, l'expression devient quelque chose comme ceci:

1. * (20-10) / (100-10)

Comme je fais toujours une division pour une formule comme:

accuracy = 1. * (len(y_val) - sum(y_val)) / len(y_val)

il est donc impossible d'ajouter simplement un élément .0similaire 20.0. Et dans mon cas, l'emballage avec un float()peut perdre un peu de lisibilité.

FredNous
la source