Czy istnieje sposób na krok od 0 do 1 o 0,1?
Myślałem, że mogę to zrobić w następujący sposób, ale się nie udało:
for i in range(0, 1, 0.1):
print i
Zamiast tego mówi, że argument kroku nie może wynosić zero, czego się nie spodziewałem.
python
floating-point
range
Evan Fosmark
źródło
źródło
itertools.takewhile
iitertools.count
. Nie jest to jednak lepsze niżdrange
wydajność.seq
narzędzie w jądrach GNU pozwala obejść sięseq 0 0.1 1
bez błędów zaokrąglania!seq
używa Clong double
typu wewnętrznego i są podatne na błędy zaokrągleń. Na przykład na mojej maszynieseq 0 0.1 1
daje1
jako ostatnie wyjście (zgodnie z oczekiwaniami), aleseq 1 0.1 2
daje1.9
jako ostatnie wyjście (zamiast oczekiwanych2
).itertools.takewhile(lambda x: (x+0.05)<1, itertools.count(0,0.1))
lubitertools.islice(itertools.count(0,0.1), 10)
(jeśli maszimport itertools
), chociaż nie przetestowałem, która jest bardziej wydajnaOdpowiedzi:
Zamiast bezpośrednio używać dziesiętnego kroku, o wiele bezpieczniej jest wyrazić to w kategoriach liczby punktów. W przeciwnym razie błąd zaokrąglenia zmiennoprzecinkowego może dać zły wynik.
Możesz użyć funkcji linspace z biblioteki NumPy (która nie jest częścią standardowej biblioteki, ale jest stosunkowo łatwa do uzyskania).
linspace
wymaga wielu punktów do zwrócenia, a także pozwala określić, czy dołączyć odpowiedni punkt końcowy:Jeśli naprawdę chcesz użyć wartości kroku zmiennoprzecinkowego, możesz za pomocą
numpy.arange
.Zmiennoprzecinkową błąd zaokrąglenia będzie powodować problemy, choć. Oto prosty przypadek, w którym błąd zaokrąglenia powoduje
arange
utworzenie tablicy o długości 4, gdy powinna ona wygenerować tylko 3 liczby:źródło
np.linspace(1.,1.3,4)
inp.arange(1.,1.3,0.1)
podaję dokładnie to samo wyjście[start,stop)
(tzn. z wyłączeniemstop
), więc nie można oczekiwać, że 1.3 zostanie uwzględniony na liście. Zobacz to pytanie, aby dowiedzieć się, dlaczego jest ono nadal uwzględniane i co zrobić z tym.Zakres () Pythona może wykonywać tylko liczby całkowite, a nie zmiennoprzecinkowe. W twoim konkretnym przypadku możesz zamiast tego użyć zrozumienia listy:
(Zamień wywołanie zakresu na to wyrażenie).
W bardziej ogólnym przypadku możesz napisać niestandardową funkcję lub generator.
źródło
(x * 0.1 for x in range(0, 10))
.x/10
zamiast tegox * 0.1
: D Właściwie nic specjalnego, ale niektóre liczby będą bardziej precyzyjne, np. Za3*0.1
dostaniesz0.30000000000000004
, a za 3/10 dostaniesz0.3
:)from __future__ import division; 3/10
zwraca 0.3. To zachowanie jest domyślne w Pythonie 3.x.Opierając się na „xrange ([start], stop [, krok])” , możesz zdefiniować generator, który akceptuje i produkuje dowolny wybrany typ (trzymaj się typów obsługujących
+
i<
):źródło
Zwiększ wielkość
i
pętli, a następnie zmniejsz ją, gdy jej potrzebujesz.EDYCJA: Naprawdę nie pamiętam, dlaczego myślałem, że to działa składniowo
To powinno mieć pożądaną moc wyjściową.
źródło
for i * 100 in range(0, 100, 10)
: Błąd składni: nie można przypisać do operatorascipy
ma wbudowaną funkcję,arange
która uogólniarange()
konstruktor Pythona, aby spełnić twoje wymagania dotyczące obsługi float.from scipy import arange
źródło
arange
co można znaleźć w numpy:>>> import scipy >>> import numpy >>> numpy.arange is scipy.arange
zwróciTrue
.from nump import arange as range
Myślę, że NumPy to trochę przesada.
Ogólnie rzecz biorąc, aby zrobić krok po kroku
1/x
w górę doy
zrobiłbyś(
1/x
wytwarzałem mniej hałasu zaokrąglania podczas testowania).źródło
Podobnie jak
seq
funkcja R , ta zwraca sekwencję w dowolnej kolejności, biorąc pod uwagę prawidłową wartość kroku. Ostatnia wartość jest równa wartości stop.Wyniki
źródło
seq(0.5, 3.0)
powraca[0.5, 1.5, 2.5, 3.5]
. Aby uniknąć sytuacji, w której ostatnie wpisy są poza zasięgiem, zastąpn = int(round(...
jen = int(floor(...
liniąfrom math import floor
u góry (powyżejdef seq(...
).floor
zostanie użyty,seq(0.2, 0.9, 0.1)
nie osiągnie właściwego punktu końcowego i powróci[0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7, 0.8]
Obawiam się, że wbudowana funkcja range () zwraca ciąg wartości liczb całkowitych, więc nie można jej użyć do zrobienia dziesiętnego kroku.
Powiedziałbym po prostu użyć pętli while:
Jeśli jesteś ciekawy, Python konwertuje 0,1 na 0, dlatego mówi ci, że argument nie może wynosić zero.
źródło
.1
10 razy to nie to samo, co dodanie1
! docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.htmlOto rozwiązanie za pomocą itertools :
Przykład użycia:
źródło
w Pythonie 2.7x daje wynik:
ale jeśli użyjesz:
daje pożądane:
źródło
źródło
A jeśli robisz to często, możesz zapisać wygenerowaną listę
r
źródło
more_itertools
to biblioteka innej firmy, która implementujenumeric_range
narzędzie:Wynik
To narzędzie działa również dla
Decimal
iFraction
.źródło
Moje wersje używają oryginalnej funkcji zakresu do tworzenia multiplikatywnych wskaźników dla zmiany. Pozwala to na taką samą składnię jak w pierwotnej funkcji zakresu. Zrobiłem dwie wersje, jedną z użyciem liczb zmiennoprzecinkowych i jedną z liczbami dziesiętnymi, ponieważ odkryłem, że w niektórych przypadkach chciałem uniknąć znoszenia zaokrągleń wprowadzonego przez arytmetykę zmiennoprzecinkową.
Jest to zgodne z wynikami pustego zestawu, jak w zakresie / zakres.
Przekazanie tylko jednej wartości liczbowej do dowolnej funkcji spowoduje zwrócenie wyjściowego zakresu standardowego do całkowitej wartości parametru wejściowego na wartość całkowitą (więc jeśli dasz mu wartość 5.5, zwróci zakres (6).)
Edycja: poniższy kod jest teraz dostępny jako pakiet na pypi : Franges
źródło
frange
działać, jeśli jest stopNone
? Ta część kodu nawet nie uwzględnia rozmiaru kroku.range
ma dwa podpisy:range(stop)
który przyjmuje wartość domyślnąstart=0, step=1
, irange(start, stop, step)
gdzie nie są przyjmowane żadne założenia.frange
odzwierciedla to. Podczas korzystania zrange(stop)
podpisu, zarównofrange
idrange
zaczynają się od 0 i przyrost o 1, więc ich zachowanie jest identyczne do regularnychrange(stop)
zachowań z przystanku zaokrągla się w górę do najbliższej liczby całkowitej.To jest moje rozwiązanie, aby uzyskać zakresy z krokami zmiennoprzecinkowymi.
Korzystając z tej funkcji, nie trzeba importować numpy ani instalować jej.
Jestem prawie pewien, że można to poprawić i zoptymalizować. Możesz to zrobić i opublikować tutaj.
Dane wyjściowe to:
źródło
Dla kompletności butiku funkcjonalne rozwiązanie:
źródło
Możesz użyć tej funkcji:
źródło
list(frange(99.8, 100.1, 0.1)) => [99.7, 99.80000000000001, 99.9]
Sztuką uniknąć zaokrąglić problemu jest użycie oddzielnego numeru do poruszania się w przedziale, który uruchamia i pół krok naprzód od początku .
Alternatywnie
numpy.arange
można zastosować.źródło
Można to zrobić za pomocą biblioteki Numpy. Funkcja arange () umożliwia wykonywanie kroków w trybie zmiennoprzecinkowym. Zwraca jednak tablicę numpy, którą można konwertować na listę za pomocą tolist () dla naszej wygody.
źródło
Moja odpowiedź jest podobna do innych używających map (), bez potrzeby użycia NumPy i bez używania lambda (choć można). Aby uzyskać listę wartości zmiennoprzecinkowych od 0,0 do t_max w krokach dt:
źródło
Zaskoczony, nikt jeszcze nie wspomniał o zalecanym rozwiązaniu w dokumentacji Python 3 :
Po zdefiniowaniu przepis jest łatwy w użyciu i nie wymaga
numpy
żadnych zewnętrznych bibliotek, ale działa podobnienumpy.linspace()
. Zauważ, że zamiaststep
argumentu trzecinum
argument określa liczbę pożądanych wartości, na przykład:Cytuję zmodyfikowaną wersję pełnego przepisu na Python 3 od Andrew Barnerta poniżej:
źródło
Aby przeciwdziałać problemom z precyzją zmiennoprzecinkową, możesz użyć
Decimal
modułu .Wymaga to dodatkowego wysiłku przekształcania się
Decimal
zint
lubfloat
podczas pisania kodu, ale można zamiast przejśćstr
i modyfikować funkcję, jeśli tego rodzaju wygody jest rzeczywiście konieczne.Przykładowe wyniki -
źródło
Decimal
wejściaminp.arange
działa tak samo:np.arange(Decimal('-2.0'), Decimal('2.0'), Decimal('0.1'))
Dodaj automatyczną korektę pod kątem możliwości nieprawidłowego podpisania w kroku:
źródło
Moje rozwiązanie:
źródło
Najlepsze rozwiązanie: brak błędu zaokrąglania
_________________________________________________________________________________
_________________________________________________________________________________
Lub, dla ustawionego zakresu zamiast ustawionych punktów danych (np. Funkcja ciągła), użyj:
Aby zaimplementować funkcję zamienić
x / pow(step, -1)
zf( x / pow(step, -1) )
, i zdefiniowaćf
.Na przykład:
źródło
start i stop są włączające, a nie jeden lub drugi (zwykle stop jest wykluczony) i bez importu oraz przy użyciu generatorów
źródło
Wiem, że spóźniłem się na przyjęcie tutaj, ale oto trywialne rozwiązanie generatora działające w wersji 3.6:
wtedy możesz nazwać to tak, jak oryginał
range()
... nie ma obsługi błędów, ale daj mi znać, jeśli istnieje błąd, który można rozsądnie wykryć, a ja zaktualizuję. lub możesz to zaktualizować. to jest StackOverflow.źródło
Oto moje rozwiązanie, które działa dobrze z float_range (-1, 0, 0,01) i działa bez błędów reprezentacji zmiennoprzecinkowej. Nie jest bardzo szybki, ale działa dobrze:
źródło
Jestem tylko początkującym, ale miałem ten sam problem podczas symulacji niektórych obliczeń. Oto jak próbowałem to rozpracować, co wydaje się działać z krokami dziesiętnymi.
Jestem też dość leniwy i dlatego trudno mi było napisać własną funkcję zakresu.
Zasadniczo to, co zrobiłem, zmieniło moje
xrange(0.0, 1.0, 0.01)
naxrange(0, 100, 1)
i zastosowało podział100.0
w pętli. Martwiłem się również, czy pojawią się błędy w zaokrąglaniu. Postanowiłem więc sprawdzić, czy są jakieś. Teraz słyszałem, że jeśli na przykład0.01
z obliczeń nie jest dokładnie zmiennoprzecinkowe0.01
porównanie ich powinno zwrócić False (jeśli się mylę, proszę dać mi znać).Dlatego postanowiłem przetestować, czy moje rozwiązanie będzie działać dla mojego zakresu, uruchamiając krótki test:
I wydrukował True dla każdego.
Teraz, jeśli popełniam błąd, daj mi znać.
źródło
Ta jedna linijka nie zaśmieci twojego kodu. Ważny jest znak parametru kroku .
źródło