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)
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)
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])
Numpy est un composant tellement omniprésent de python que je considère cette réponse comme la plus "pythonique" de toutes.
@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.
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
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)
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))
.
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
:)
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']
>>>
Il y a des problèmes d'arrondis. Veuillez consulter cette page : code.activestate.com/recipes/66472
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.
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]
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é.
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.
@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é.
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.
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
yitertools.count
. Il n'est pas meilleur quedrange
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 suivantesseq 0 0.1 1
sans erreur d'arrondi !3 votes
@josch :
seq
utilise le système Clong double
en interne, et es sous réserve d'erreurs d'arrondi. Par exemple, sur ma machine,seq 0 0.1 1
donne1
comme dernière sortie (comme prévu), maisseq 1 0.1 2
donne1.9
comme dernier résultat (au lieu du résultat attendu2
).1 votes
Pour plus de commodité, la suggestion de @Kos peut être mise en œuvre sous la forme suivante
itertools.takewhile(lambda x: (x+0.05)<1, itertools.count(0,0.1))
oitertools.islice(itertools.count(0,0.1), 10)
(après avoirimport itertools
), bien que je n'aie pas testé lequel est le plus efficace