Existe-t-il un moyen de passer de 0 à 1 de 0,1?
Je pensais que je pouvais le faire comme suit, mais cela a échoué:
for i in range(0, 1, 0.1):
print i
Au lieu de cela, il dit que l'argument step ne peut pas être nul, ce à quoi je ne m'attendais pas.
python
floating-point
range
Evan Fosmark
la source
la source
itertools.takewhile
etitertools.count
. Ce n'est pas mieux que pour lesdrange
performances.seq
outil dans GNU coreutils permet de se passer desseq 0 0.1 1
erreurs d'arrondi!seq
utilise lelong double
type C en interne et est sujet aux 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 dernière sortie (plutôt que prévu2
).itertools.takewhile(lambda x: (x+0.05)<1, itertools.count(0,0.1))
ouitertools.islice(itertools.count(0,0.1), 10)
(après vous l'avezimport itertools
), bien que je n'ai pas testé ce qui est plus efficaceRéponses:
Plutôt que d'utiliser directement un pas décimal, il est beaucoup plus sûr d'exprimer cela en termes de nombre de points que vous souhaitez. Sinon, une erreur d'arrondi à virgule flottante est susceptible de vous donner un mauvais résultat.
Vous pouvez utiliser la fonction linspace de la bibliothèque NumPy (qui ne fait pas partie de la bibliothèque standard mais est relativement facile à obtenir).
linspace
prend un certain nombre de points à renvoyer et vous permet également de spécifier s'il faut inclure le bon point de terminaison:Si vous voulez vraiment utiliser une valeur de pas à virgule flottante, vous pouvez, avec
numpy.arange
.Erreur d'arrondi à virgule flottante va causer des problèmes, cependant. Voici un cas simple où une erreur d'arrondi provoque la
arange
production d'un tableau de longueur 4 alors qu'il ne devrait produire que 3 nombres:la source
np.linspace(1.,1.3,4)
etnp.arange(1.,1.3,0.1)
donne exactement la même sortie[start,stop)
(c'est-à-dire excluantstop
), donc on ne s'attendrait pas à ce que 1.3 soit inclus dans la liste. Voir cette question pour savoir pourquoi elle est toujours incluse et que faire contre elle.Le range () de Python ne peut faire que des entiers, pas des virgules flottantes. Dans votre cas spécifique, vous pouvez utiliser une compréhension de liste à la place:
(Remplacez l'appel à range par cette expression.)
Pour le cas plus général, vous souhaiterez peut-être écrire une fonction ou un générateur personnalisé.
la source
(x * 0.1 for x in range(0, 10))
.x/10
place dex * 0.1
: D Rien de spécial en fait, mais certains chiffres seront plus précis, par exemple pour3*0.1
vous0.30000000000000004
, alors que pour 3/10 vous obtenez0.3
:)from __future__ import division; 3/10
renvoie 0.3. Ce comportement est le comportement par défaut dans Python 3.x.En vous appuyant sur «xrange ([start], stop [, step])» , vous pouvez définir un générateur qui accepte et produit le type de votre choix (respectez les types prenant en charge
+
et<
):la source
Augmentez l'amplitude de
i
la boucle, puis réduisez-la lorsque vous en avez besoin.EDIT: Honnêtement, je ne me souviens pas pourquoi je pensais que cela fonctionnerait syntaxiquement
Cela devrait avoir la sortie souhaitée.
la source
for i * 100 in range(0, 100, 10)
: SyntaxError: impossible d'attribuer à l'opérateurscipy
a une fonction intégréearange
qui généralise lerange()
constructeur de Python pour satisfaire votre exigence de gestion des flottants.from scipy import arange
la source
arange
vous pouvez trouver dans numpy:>>> import scipy >>> import numpy >>> numpy.arange is scipy.arange
reviendraTrue
.from nump import arange as range
NumPy est un peu exagéré, je pense.
De manière générale, faire un pas
1/x
versy
vous ferait(
1/x
produit moins de bruit d'arrondi lorsque j'ai testé).la source
Semblable à la
seq
fonction de R , celle-ci renvoie une séquence dans n'importe quel ordre étant donné la valeur de pas correcte. La dernière valeur est égale à la valeur d'arrêt.Résultats
la source
seq(0.5, 3.0)
revient[0.5, 1.5, 2.5, 3.5]
. Pour éviter les entrées dernières étant hors de portée, remplacern = int(round(...
avecn = int(floor(...
la lignefrom math import floor
en haut ( au- dessusdef seq(...
).floor
est utilisé,seq(0.2, 0.9, 0.1)
ne parviendra pas à atteindre le point final droit et reviendra[0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7, 0.8]
La fonction intégrée range () renvoie une séquence de valeurs entières, je le crains, vous ne pouvez donc pas l'utiliser pour faire un pas décimal.
Je dirais qu'il suffit d'utiliser une boucle while:
Si vous êtes curieux, Python convertit votre 0,1 en 0, c'est pourquoi il vous dit que l'argument ne peut pas être nul.
la source
.1
10 fois n'est pas la même chose que d'ajouter1
! docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.htmlVoici une solution utilisant itertools :
Exemple d'utilisation:
la source
en Python 2.7x vous donne le résultat de:
mais si vous utilisez:
vous donne le souhaité:
la source
la source
Et si vous le faites souvent, vous voudrez peut-être enregistrer la liste générée
r
la source
more_itertools
est une bibliothèque tierce qui implémente unnumeric_range
outil:Production
Cet outil fonctionne également pour
Decimal
etFraction
.la source
Mes versions utilisent la fonction de plage d'origine pour créer des indices multiplicatifs pour le décalage. Cela permet la même syntaxe à la fonction de plage d'origine. J'ai fait deux versions, une utilisant float et une utilisant Decimal, car j'ai trouvé que dans certains cas, je voulais éviter la dérive d'arrondi introduite par l'arithmétique à virgule flottante.
Il est cohérent avec des résultats d'ensemble vides comme dans range / xrange.
Le passage d'une seule valeur numérique à l'une ou l'autre fonction ramènera la sortie de la plage standard à la valeur plafond entière du paramètre d'entrée (donc si vous lui donniez 5.5, elle retournerait la plage (6).)
Edit: le code ci-dessous est désormais disponible en package sur pypi: Franges
la source
frange
fonctionner si l'arrêt estNone
? Cette partie du code ne prend même plus en compte la taille de l'étape.range
a deux signatures :,range(stop)
qui suppose une valeur par défautstart=0, step=1
, etrange(start, stop, step)
, où aucune hypothèse n'est faite.frange
reflète cela. Lorsque vous utilisez larange(stop)
signature, les deuxfrange
etdrange
commencent à 0 et incrémentent de 1, de sorte que leur comportement est identique aurange(stop)
comportement normal avec un arrêt arrondi à l'entier le plus proche.Ceci est ma solution pour obtenir des plages avec des étapes flottantes.
En utilisant cette fonction, il n'est pas nécessaire d'importer numpy, ni de l'installer.
Je suis sûr que cela pourrait être amélioré et optimisé. N'hésitez pas à le faire et à le poster ici.
La sortie est:
la source
Pour l'exhaustivité de la boutique, une solution fonctionnelle:
la source
Vous pouvez utiliser cette fonction:
la source
list(frange(99.8, 100.1, 0.1)) => [99.7, 99.80000000000001, 99.9]
L'astuce pour éviter les problèmes d'arrondi consiste à utiliser un numéro distinct pour se déplacer dans la plage, qui commence et la moitié du pas avant le début .
Alternativement,
numpy.arange
peut être utilisé.la source
Cela peut être fait en utilisant la bibliothèque Numpy. La fonction arange () permet des étapes dans float. Mais, il retourne un tableau numpy qui peut être converti en liste en utilisant tolist () pour notre commodité.
la source
Ma réponse est similaire à d'autres utilisant map (), sans avoir besoin de NumPy, et sans utiliser lambda (bien que vous puissiez). Pour obtenir une liste de valeurs flottantes de 0,0 à t_max par pas de dt:
la source
Personne surpris n'a encore mentionné la solution recommandée dans les documents Python 3 :
Une fois définie, la recette est facile à utiliser et ne nécessite
numpy
ni aucune autre bibliothèque externe, mais fonctionne commenumpy.linspace()
. Notez que plutôt qu'unstep
argument, le troisièmenum
argument spécifie le nombre de valeurs souhaitées, par exemple:Je cite ci-dessous une version modifiée de la recette complète de Python 3 d'Andrew Barnert:
la source
Pour contrer les problèmes de précision du flotteur, vous pouvez utiliser le
Decimal
module .Cela nécessite un effort supplémentaire de conversion en ou
Decimal
depuis l' écriture du code, mais vous pouvez à la place passer et modifier la fonction si ce genre de commodité est en effet nécessaire.int
float
str
Exemples de sorties -
la source
Decimal
entrées similaires ,np.arange
fonctionne de la même manière:np.arange(Decimal('-2.0'), Decimal('2.0'), Decimal('0.1'))
Ajoutez une correction automatique pour la possibilité d'une étape de connexion incorrecte:
la source
Ma solution:
la source
Meilleure solution: aucune erreur d'arrondi
_________________________________________________________________________________
_________________________________________________________________________________
Ou, pour une plage définie au lieu de points de données définis (par exemple, une fonction continue), utilisez:
Pour implémenter une fonction: remplacez
x / pow(step, -1)
parf( x / pow(step, -1) )
et définissezf
.Par exemple:
la source
le démarrage et l'arrêt sont inclusifs plutôt que l'un ou l'autre (généralement l'arrêt est exclu) et sans importations, et en utilisant des générateurs
la source
Je sais que je suis en retard à la fête ici, mais voici une solution de générateur triviale qui fonctionne en 3.6:
alors vous pouvez l'appeler comme l'original
range()
... il n'y a pas de gestion d'erreur, mais faites-moi savoir s'il y a une erreur qui peut être raisonnablement détectée, et je mettrai à jour. ou vous pouvez le mettre à jour. c'est StackOverflow.la source
Voici ma solution qui fonctionne très bien avec float_range (-1, 0, 0.01) et fonctionne sans erreurs de représentation en virgule flottante. Ce n'est pas très rapide, mais fonctionne très bien:
la source
Je ne suis qu'un débutant, mais j'ai eu le même problème lors de la simulation de certains calculs. Voici comment j'ai essayé de résoudre ce problème, qui semble fonctionner avec des étapes décimales.
Je suis également assez paresseux et j'ai donc eu du mal à écrire ma propre fonction de plage.
En fait ce que je l'ai fait est changé ma
xrange(0.0, 1.0, 0.01)
pourxrange(0, 100, 1)
et utilisé par la division à l'100.0
intérieur de la boucle. J'étais également inquiet, s'il y aurait des erreurs d'arrondi. J'ai donc décidé de tester, s'il y en a. Maintenant, j'ai entendu dire que si, par exemple, à0.01
partir d'un calcul, le flotteur les0.01
comparant ne devait pas exactement retourner Faux (si je me trompe, faites-le moi savoir).J'ai donc décidé de tester si ma solution fonctionnerait pour ma gamme en lançant un court test:
Et il a imprimé True pour chacun.
Maintenant, si je me trompe totalement, faites-le moi savoir.
la source
Cette doublure n'encombrera pas votre code. Le signe du paramètre step est important.
la source