Chcę uzyskać listę liczb, takich jak [-2.3,-2.2,...,0.2] w Python. Jednak próba:

[float(i)/10 for i in range(-23,2)] 

Wróci [-2.2999999999999998, -2.2000000000000002, -2.1000000000000001, -2.0, -1.8999999999999999, -1.8, -1.7, -1.6000000000000001, -1.5, -1.3999999999999999, -1.3, -1.2, -1.1000000000000001, -1.0, -0.90000000000000002, -0.80000000000000004, -0.69999999999999996, -0.59999999999999998, -0.5, -0.40000000000000002, -0.29999999999999999, -0.20000000000000001, -0.10000000000000001, 0.0]

Jak to naprawić?

Runda nie działa:

>>> round(float(-23)/float(10),3)
-2.2999999999999998

Jest to dla ewentualnego zapisu do CSV lub przejść do innego języka poprzez metodę główną.

1
user2763361 20 listopad 2013, 11:04

5 odpowiedzi

Najlepsza odpowiedź

Proszę nie mylić, jak coś powinno wyglądać, gdy jego drukowane w porównaniu z tym, co powinno reprezentować jako jego wartość.

Drukowanie nigdy nie jest problemem:

>>> ['{0:.1f}'.format(float(i)/10) for i in range(-23,3)]
['-2.3', '-2.2', '-2.1', '-2.0', '-1.9', '-1.8', '-1.7', '-1.6', '-1.5', '-1.4', '-1.3', '-1.2', '-1.1', '-1.0', '-0.9', '-0.8', '-0.7', '-0.6', '-0.5', '-0.4', '-0.3', '-0.2', '-0.1', '0.0', '0.1', '0.2']

Ale to są ciągi, ponieważ to ich drukowana reprezentacja. Kiedy prowadzisz obliczenia, potrzebujesz reprezentacji pływakowej, która nie jest dokładna; jak wskazał @mitnk; A jak wyjaśniono @ 6502.

Możesz także użyć {x0}} moduł który zapewnia więcej przyjaznych dla ludzi reprezentacja numerów pływających punktów.

5
Burhan Khalid 20 listopad 2013, 07:24

Przyczyną jest -2.3 zasadniczo nie może precyzyjnie reprezentować jako bitów, a {x1}} jest najbliższym do -2.3 i może reprezentować jako bitów.

Więcej czytania: http://docs. personhon.org/2/Tutorial/floatingpoint.html http://en.wikipedia.org/wiki/floating_point

3
mitnk 20 listopad 2013, 07:11

Właśnie jak działają liczby pływających punktów. Nie są precyzyjni

Podczas wyświetlania użyj formatu

print "%.2f" % a
2
evhen14 20 listopad 2013, 07:15

Jedyne numery, które mogą być reprezentowane dokładnie w standardowym formacie pływającego IEEE, są formularza num/den, gdzie oba są liczbami całkowitymi, a gdzie {X1}} jest integralną moc dwóch.

Oznacza to, że liczby takie jak 1/10 muszą być przybliżone na przykład do 900719925474099/9007199254740992, który jest wystarczająco blisko, aby 1/10, ale ma 1<<53 jako mianownik.

Innymi słowy 1/10 = 0.1 jest to liczba, w której wyrażona w postaci binarnej jest okresowa i wymagałaby reprezentowania nieskończonej liczby cyfr. To, co dzieje się, że 1/10 jest obcięty do ustalonej liczby cyfr binarnych i może być reprezentowany tylko z przybliżeniem.

0.1 nie można reprezentować w binarnym dokładnie tak, jak 1/3 = 0.333333... jest niemożliwe, aby reprezentować skończoną liczbą cyfr w dziesiętnie.

Python jest po prostu różni się od innych języków, jak domyślnie próbuje powiedzieć prawdę podczas konwersji liczby w dziesiętnie do drukowania. Możesz oczywiście "okrągły" numer do drukowania, ale fakt, że 1.3 jest na przykład niemożliwe do reprezentowania dokładnie w IEEE Pływający punkt.

Należy również pamiętać, że range(start, stop) wygeneruje elementy z start do stop, ale z wyłączeniem stop (Logika interwałowa na wpół otenowie). Jeśli chcesz również ten element, użyj range(start, stop+1).

Funkcja próbkowania przedziału pływającego jest obecna w numpry, ale nie jest częścią standardowej biblioteki Python. W wersjach preferuję jednak nie określam kroku, ale liczby próbek (aby uniknąć problemów z dokładnością):

def sample_interval(a, b, n):
    delta = float(b - a) / n
    a += delta / 2
    return [a + i*delta for i in xrange(n)]
1
6502 20 listopad 2013, 08:19

Odpowiedzi do tej pory wyjaśniają, co się dzieje, ale jest jeszcze jedna ważna część do układanki. Używasz Python 2.x, jeśli używasz Pythona 3 (i chyba że masz powodu, nie do, naprawdę powinieneś), nigdy nie zadałbyś pytania.

W Pythonie 3:

>>> [float(i)/10 for i in range(-23,2)]
[-2.3, -2.2, -2.1, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1]

Liczby są nadal przechowywane dokładnie w ten sam sposób, ale Python 3 wie, że zarówno -2.2999999999999998, jak i -2.3 mają tę samą reprezentację, więc wybiera domyślnie format z mniejszą liczbą cyfr. Nadal musisz zrozumieć, że nie przechowuje się wartości, która jest dokładnie -2.3, ale przynajmniej domyślne wyjście wygląda nieco czyszczenia.

0
Duncan 20 listopad 2013, 09:57