Gibt es eine Möglichkeit, um 0,1 zwischen 0 und 1 zu wechseln?
Ich dachte, ich könnte es wie folgt machen, aber es schlug fehl:
for i in range(0, 1, 0.1):
print i
Stattdessen heißt es, dass das Schrittargument nicht Null sein kann, was ich nicht erwartet hatte.
python
floating-point
range
Evan Fosmark
quelle
quelle
itertools.takewhile
und aufgerollt werdenitertools.count
. Es ist jedoch nicht besser als diedrange
Leistung.seq
Tool in GNU Coreutils kann man aufseq 0 0.1 1
Rundungsfehler verzichten!seq
verwendet den C -long double
Typen intern und ist Gegenstand von Rundungsfehlern. Zum Beispiel auf meiner Maschine,seq 0 0.1 1
gibt1
als letzte Ausgabe (wie erwartet), sondernseq 1 0.1 2
gibt1.9
als letzte Ausgabe ( und nicht den erwarteten2
).itertools.takewhile(lambda x: (x+0.05)<1, itertools.count(0,0.1))
oderitertools.islice(itertools.count(0,0.1), 10)
(nachdem Sie dies getan habenimport itertools
) implementiert werden , obwohl ich nicht getestet habe, was effizienter istAntworten:
Anstatt einen Dezimalschritt direkt zu verwenden, ist es viel sicherer, dies in Bezug auf die Anzahl der gewünschten Punkte auszudrücken. Andernfalls führt ein Gleitkomma-Rundungsfehler wahrscheinlich zu einem falschen Ergebnis.
Sie können die Linspace- Funktion aus der NumPy- Bibliothek verwenden (die nicht Teil der Standardbibliothek ist, aber relativ einfach zu erhalten ist).
linspace
Für die Rückgabe sind mehrere Punkte erforderlich. Außerdem können Sie angeben, ob der richtige Endpunkt eingeschlossen werden soll oder nicht:Wenn Sie wirklich einen Gleitkomma-Schrittwert verwenden möchten, können Sie mit
numpy.arange
.Gleitkommazahlen Rundungsfehler wird zu Problemen führen, wenn. Hier ist ein einfacher Fall, in dem Rundungsfehler dazu führen
arange
, dass ein Array mit einer Länge von 4 erzeugt wird, wenn nur 3 Zahlen erzeugt werden sollen:quelle
np.linspace(1.,1.3,4)
undnp.arange(1.,1.3,0.1)
gebe genau die gleiche Ausgabe[start,stop)
(dh ausschließtstop
), sodass man nicht erwarten würde, dass 1.3 in die Liste aufgenommen wird. In dieser Frage erfahren Sie, warum sie noch enthalten ist und was Sie dagegen tun können.Pythons range () kann nur Ganzzahlen ausführen, keine Gleitkommazahlen. In Ihrem speziellen Fall können Sie stattdessen ein Listenverständnis verwenden:
(Ersetzen Sie den Aufruf zum Bereich durch diesen Ausdruck.)
Für den allgemeineren Fall möchten Sie möglicherweise eine benutzerdefinierte Funktion oder einen benutzerdefinierten Generator schreiben.
quelle
(x * 0.1 for x in range(0, 10))
.x/10
stattx * 0.1
: D Eigentlich nichts Besonderes, aber einige Zahlen dort werden präziser sein, z. B. für3*0.1
Sie0.30000000000000004
, während Sie für 3/10 erhalten0.3
:)from __future__ import division; 3/10
0.3 zurück. Dieses Verhalten ist die Standardeinstellung in Python 3.x.Aufbauend auf 'xrange ([start], stop [, step])' können Sie einen Generator definieren, der jeden von Ihnen gewählten Typ akzeptiert und erzeugt (halten Sie sich an unterstützende Typen
+
und<
):quelle
Erhöhen Sie die Größe
i
der Schleife und verringern Sie sie dann, wenn Sie sie benötigen.EDIT: Ich kann mich ehrlich gesagt nicht erinnern, warum ich dachte, dass das syntaktisch funktionieren würde
Das sollte die gewünschte Leistung haben.
quelle
for i * 100 in range(0, 100, 10)
: SyntaxError: kann nicht dem Operator zugewiesen werdenscipy
verfügt über eine integrierte Funktion,arange
die den Python-range()
Konstruktor verallgemeinert , um Ihre Anforderungen an die Float-Behandlung zu erfüllen.from scipy import arange
quelle
arange
, was Sie in numpy finden können:>>> import scipy >>> import numpy >>> numpy.arange is scipy.arange
wird zurückkehrenTrue
.from nump import arange as range
NumPy ist ein bisschen übertrieben, denke ich.
Im Allgemeinen würde es genügen, einen Schritt nach
1/x
oben zuy
machen(
1/x
erzeugte weniger Rundungsgeräusche, als ich testete).quelle
Ähnlich wie bei der
seq
Funktion von R gibt diese eine Sequenz in beliebiger Reihenfolge mit dem richtigen Schrittwert zurück. Der letzte Wert entspricht dem Stoppwert.Ergebnisse
quelle
seq(0.5, 3.0)
zurückkehrt[0.5, 1.5, 2.5, 3.5]
. Um zu vermeiden , letzte Einträge sind out-of-Bereich, ersetzen Sien = int(round(...
mitn = int(floor(...
der Liniefrom math import floor
an der Spitze ( siehe obendef seq(...
).floor
es verwendet wird, erreichtseq(0.2, 0.9, 0.1)
es nicht den richtigen Endpunkt und kehrt zurück[0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7, 0.8]
Die integrierte Funktion range () gibt leider eine Folge von ganzzahligen Werten zurück, sodass Sie sie nicht für einen Dezimalschritt verwenden können.
Ich würde sagen, benutze einfach eine while-Schleife:
Wenn Sie neugierig sind, konvertiert Python Ihre 0.1 in 0, weshalb es Ihnen sagt, dass das Argument nicht Null sein kann.
quelle
.1
10- maliges Hinzufügen ist nicht dasselbe wie Hinzufügen1
! docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.htmlHier ist eine Lösung mit itertools :
Anwendungsbeispiel:
quelle
In Python 2.7x erhalten Sie das Ergebnis von:
aber wenn Sie verwenden:
gibt Ihnen das gewünschte:
quelle
quelle
Wenn Sie dies häufig tun, möchten Sie möglicherweise die generierte Liste speichern
r
quelle
more_itertools
ist eine Bibliothek eines Drittanbieters, die einnumeric_range
Tool implementiert :Ausgabe
Dieses Tool funktioniert auch für
Decimal
undFraction
.quelle
Meine Versionen verwenden die ursprüngliche Bereichsfunktion, um multiplikative Indizes für die Verschiebung zu erstellen. Dies ermöglicht die gleiche Syntax wie die ursprüngliche Bereichsfunktion. Ich habe zwei Versionen erstellt, eine mit float und eine mit Decimal, weil ich festgestellt habe, dass ich in einigen Fällen die durch die Gleitkomma-Arithmetik verursachte Rundungsdrift vermeiden wollte.
Dies stimmt mit den Ergebnissen der leeren Menge wie in range / xrange überein.
Wenn Sie nur einen einzigen numerischen Wert an eine der beiden Funktionen übergeben, wird die Standardbereichsausgabe auf den ganzzahligen Höchstwert des Eingabeparameters zurückgesetzt. Wenn Sie also 5,5 angeben, wird der Bereich (6) zurückgegeben.)
Bearbeiten: Der folgende Code ist jetzt als Paket auf pypi: Franges verfügbar
quelle
frange
funktionieren, wenn Stopp istNone
? Dieser Teil des Codes berücksichtigt nicht einmal mehr die Schrittgröße.range
hat zwei Signaturen :range(stop)
, die einen Standard annehmenstart=0, step=1
, undrange(start, stop, step)
bei denen keine Annahmen getroffen werden.frange
spiegelt das wider. Bei Verwendung derrange(stop)
Unterschrift, die beidefrange
unddrange
bei 0 und Schrittweite von 1 beginnen, so dass ihr Verhalten regelmäßig identisch istrange(stop)
Verhalten mit Stop gerundet auf die nächste ganze Zahl auf.Dies ist meine Lösung, um Bereiche mit Float-Schritten zu erhalten.
Mit dieser Funktion ist es nicht erforderlich, numpy zu importieren oder zu installieren.
Ich bin mir ziemlich sicher, dass es verbessert und optimiert werden könnte. Fühlen Sie sich frei, es zu tun und es hier zu posten.
Die Ausgabe ist:
quelle
Für die Vollständigkeit der Boutique eine funktionale Lösung:
quelle
Sie können diese Funktion verwenden:
quelle
list(frange(99.8, 100.1, 0.1)) => [99.7, 99.80000000000001, 99.9]
Der Trick zu vermeiden Abrundungs Problem ist eine eigene Nummer zu verwenden , durch den Bereich zu bewegen, das beginnt und die Hälfte des Schritt vor Beginn .
Alternativ
numpy.arange
kann verwendet werden.quelle
Dies kann mit der Numpy-Bibliothek erfolgen. Die Funktion arange () ermöglicht Schritte in float. Es wird jedoch ein numpy-Array zurückgegeben, das zur Vereinfachung mit tolist () in list konvertiert werden kann.
quelle
Meine Antwort ist ähnlich wie bei anderen, die map () verwenden, ohne NumPy zu benötigen und ohne Lambda zu verwenden (obwohl Sie dies könnten). So erhalten Sie eine Liste von Gleitkommawerten von 0,0 bis t_max in Schritten von dt:
quelle
Überrascht hat noch niemand die empfohlene Lösung in den Python 3-Dokumenten erwähnt :
Einmal definiert, ist das Rezept einfach zu verwenden und erfordert keine
numpy
oder andere externe Bibliotheken, funktioniert aber wienumpy.linspace()
. Beachten Sie, dassstep
das drittenum
Argument anstelle eines Arguments die Anzahl der gewünschten Werte angibt, zum Beispiel:Ich zitiere eine modifizierte Version des vollständigen Python 3-Rezepts von Andrew Barnert unten:
quelle
Um den Problemen mit der Float-Genauigkeit entgegenzuwirken, können Sie das
Decimal
Modul verwenden .Dies erfordert einen zusätzlichen Aufwand für die Konvertierung
Decimal
vonint
oderfloat
während des Schreibens des Codes. Sie können jedoch stattdessenstr
die Funktion übergeben und ändern, wenn diese Art von Komfort tatsächlich erforderlich ist.Beispielausgaben -
quelle
Decimal
Eingabennp.arange
funktioniert das gleiche:np.arange(Decimal('-2.0'), Decimal('2.0'), Decimal('0.1'))
Fügen Sie eine automatische Korrektur für die Möglichkeit eines falschen Anmeldeschritts hinzu:
quelle
Meine Lösung:
quelle
Beste Lösung: kein Rundungsfehler
_________________________________________________________________________________
_________________________________________________________________________________
Oder verwenden Sie für einen festgelegten Bereich anstelle von festgelegten Datenpunkten (z. B. kontinuierliche Funktion):
So implementieren Sie eine Funktion: Ersetzen
x / pow(step, -1)
durchf( x / pow(step, -1) )
und definierenf
.Zum Beispiel:
quelle
Start und Stopp sind inklusive und nicht der eine oder andere (normalerweise ist Stopp ausgeschlossen) und ohne Importe und unter Verwendung von Generatoren
quelle
Ich weiß, dass ich zu spät zur Party komme, aber hier ist eine triviale Generatorlösung, die in 3.6 funktioniert:
dann können Sie es wie das Original aufrufen
range()
... es gibt keine Fehlerbehandlung, aber lassen Sie mich wissen, wenn es einen Fehler gibt, der vernünftigerweise abgefangen werden kann, und ich werde ihn aktualisieren. oder Sie können es aktualisieren. Dies ist StackOverflow.quelle
Hier ist meine Lösung, die gut mit float_range (-1, 0, 0.01) funktioniert und ohne Gleitkomma-Darstellungsfehler funktioniert. Es ist nicht sehr schnell, funktioniert aber gut:
quelle
Ich bin nur ein Anfänger, aber ich hatte das gleiche Problem, als ich einige Berechnungen simulierte. Hier ist, wie ich versucht habe, dies herauszufinden, was mit Dezimalschritten zu funktionieren scheint.
Ich bin auch ziemlich faul und fand es schwierig, meine eigene Bereichsfunktion zu schreiben.
Im Grunde , was ich getan habe ist meine geändert
xrange(0.0, 1.0, 0.01)
zuxrange(0, 100, 1)
und verwendet , um die Division durch die100.0
innerhalb der Schleife. Ich war auch besorgt, ob es Rundungsfehler geben wird. Also habe ich mich entschlossen zu testen, ob es welche gibt. Jetzt habe ich gehört, dass wenn zum Beispiel0.01
aus einer Berechnung nicht genau der Float0.01
, der sie vergleicht, False zurückgegeben werden sollte (wenn ich falsch liege, lassen Sie es mich bitte wissen).Deshalb habe ich mich entschlossen zu testen, ob meine Lösung für mein Sortiment funktioniert, indem ich einen kurzen Test durchführte:
Und es druckte True für jeden.
Wenn ich es jetzt völlig falsch verstehe, lass es mich wissen.
quelle
Dieser eine Liner wird Ihren Code nicht überladen. Das Vorzeichen des Schrittparameters ist wichtig.
quelle