985 votes

Comment utiliser une valeur décimale pour la fonction range() ?

Comment itérer entre 0 et 1 par pas de 0,1 ?

Cela signifie que l'argument du pas ne peut pas être nul :

for i in range(0, 1, 0.1):
    print(i)

20 votes

Int(0.1) == 0, donc le pas est en fait zéro. C'est peut-être inattendu, mais c'est zéro. Vous pourriez reformuler votre question pour refléter le fait que vous ne vous attendiez pas à cela. Dire "ce n'est pas" est faux et trompeur.

3 votes

BTW Un court one-liner peut être enroulé à l'aide de itertools.takewhile y itertools.count . Il n'est pas meilleur que drange en termes de performances, cependant.

4 votes

Il est embarrassant que la plage de python ne permette pas cela, étant donné la facilité avec laquelle il est possible d'implémenter un générateur qui fait cela même sans accumuler d'erreurs d'arrondi. En effet, même la fonction seq de GNU coreutils permet d'effectuer les opérations suivantes seq 0 0.1 1 sans erreur d'arrondi !

1192voto

Andrew Jaffe Points 9205

Plutôt que d'utiliser directement un pas décimal, il est beaucoup plus sûr de l'exprimer en termes de nombre de points souhaités. Sinon, l'erreur d'arrondi en virgule flottante risque de donner un résultat erroné.

Utiliser le linspace de la fonction NumPy (qui ne fait pas partie de la bibliothèque standard mais qui est relativement facile à obtenir). linspace prend un nombre de points à retourner, et vous permet également de spécifier si le point d'extrémité droit doit être inclus ou non :

>>> np.linspace(0,1,11)
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9,  1. ])
>>> np.linspace(0,1,10,endpoint=False)
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9])

Si vous souhaitez vraiment utiliser une valeur d'étape en virgule flottante, utilisez numpy.arange :

>>> import numpy as np
>>> np.arange(0.0, 1.0, 0.1)
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9])

Erreur d'arrondi en virgule flottante volonté Cependant, cela pose des problèmes. Voici un cas simple où les erreurs d'arrondi causent des problèmes. arange pour produire un tableau de longueur 4 alors qu'il ne devrait produire que 3 nombres :

>>> numpy.arange(1, 1.3, 0.1)
array([1. , 1.1, 1.2, 1.3])

71 votes

Numpy est un composant tellement omniprésent de python que je considère cette réponse comme la plus "pythonique" de toutes.

32 votes

@AndreTerra Le problème est que @numpy@ est un paquetage tiers et ajoute beaucoup de surcharge en termes de gestion des dépendances, de stockage (pour le paquetage lui-même), etc. En fonction de ce que fait le développeur, il peut être impossible de l'utiliser.

3 votes

Pardonnez-moi, mais je n'ai pas compris l'erreur d'arrondi en virgule flottante dans la dernière partie puisque np.linspace(1.,1.3,4) y np.arange(1.,1.3,0.1) donnent exactement le même résultat

295voto

Lars Wirzenius Points 12197

range() ne peut traiter que des nombres entiers, pas des nombres à virgule flottante.

Utiliser un compréhension de la liste pour obtenir une liste d'étapes :

[x * 0.1 for x in range(0, 10)]

Plus généralement, un générateur minimise les allocations de mémoire :

xs = (x * 0.1 for x in range(0, 10))
for x in xs:
    print(x)

41 votes

Mieux encore, vous pouvez utiliser la compréhension d'un générateur si vous travaillez avec Python 2.4+. (x * 0.1 for x in range(0, 10)) .

64 votes

Même mieux, mettre x/10 au lieu de x * 0.1 :D Rien de spécial en fait, mais certains nombres seront plus précis, par exemple pour 3*0.1 vous obtenez 0.30000000000000004 , tandis que pour 3/10 vous obtenez 0.3 :)

6 votes

3/10 donne 0, pas 0,3. 3/10.0 donne 0.29999999999999999. Python 2.6.

158voto

gimel Points 30150

S'appuyer sur xrange([start], stop[, step]) vous pouvez définir un générateur qui accepte et produit n'importe quel type que vous choisissez (s'en tenir aux types supportant les + y < ):

>>> def drange(start, stop, step):
...     r = start
...     while r < stop:
...         yield r
...         r += step
...         
>>> i0=drange(0.0, 1.0, 0.1)
>>> ["%g" % x for x in i0]
['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1']
>>>

51 votes

Il y a des problèmes d'arrondis. Veuillez consulter cette page : code.activestate.com/recipes/66472

0 votes

Je l'étendrais un peu dans l'autre sens avec un (while r > stop) et une étape correspondante r -= pour donner la direction opposée.

0 votes

Pour : l=frange(0,1,0.1) print l les retours : [0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7000000000000001, 0.8, 0.9] while numpy : [ 0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]

37voto

cmsjr Points 16766

Augmenter l'ampleur de la i pour la boucle et la réduire lorsque vous en avez besoin.

for i * 100 in range(0, 100, 10):
    print i / 100.0

EDIT : Honnêtement, je ne me souviens pas pourquoi j'ai pensé que cela fonctionnerait d'un point de vue syntaxique.

for i in range(0, 11, 1):
    print i / 10.0

Cela devrait donner le résultat souhaité.

1 votes

Je pense que vous découvrirez que range() fonctionne avec des entiers, auquel cas ce serait la seule solution, en utilisant au moins la même fonction.

2 votes

@cmsjr creative :D Juste une petite chose : divisez par 100.0 pour éviter que Python ne tronque le résultat si vous utilisez Python 2.x. Je pense qu'en 3.0, cela fonctionnera comme vous l'avez codé.

5 votes

for i * 100 in range(0, 100, 10) : SyntaxError : can't assign to operator (erreur de syntaxe)

24voto

fractalcows Points 51

scipy a une fonction intégrée arange qui généralise la fonction range() pour répondre à vos besoins en matière de gestion des flottants.

from scipy import arange

14 votes

Il s'agit en fait exactement de la même arange que vous pouvez trouver dans numpy : >>> import scipy >>> import numpy >>> numpy.arange is scipy.arange renverra True .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X