>>> print (12//0.2)
59.0
>>> print(floor(12/0.2))
60

Dlaczego dywizja podłogi nie działa zgodnie z zasadą w tym przypadku?

Str.s. Tutaj Python traktuje 0.2 jako 0.20000000001 w przypadku floor division Więc (12/0.2000000001) skutkuje 59.999999... I floor(59.999999999) Wydajanie {x6}} Ale nie wiem, dlaczego python traktuje 0.2 jako 0.2000000001 w etui floor division, ale nie w przypadku division?

9
Aashutosh Ranjan 26 październik 2020, 11:33

1 odpowiedź

Najlepsza odpowiedź

Powodem, dla którego 12 / 0.2 wyniki w 60.0, nie jest dlatego, że 0,2 jest traktowany inaczej, ale ponieważ błąd w podziale Punktu pływającego anuluje błąd w reprezentacji 0,2. Float zawsze ma taką samą wartość (większa niż dziesiętna 0,2), ale w zależności od operacji błędy albo gromadzą się lub zostaną anulowane.

W innych przypadkach błąd nie jest całkowicie anulowany i pojawia się w wyniku:

>>> (12 / (0.2 * 0.2)) * 0.2
59.99999999999999

W dywizji całkowitej Cysthon dla tych specyficznych typów (pływak // pływak po automatycznym przekonwertowaniu) i względne wielkościami są wykonywane w następujący sposób (patrz Kod źródłowy Pythona dla pełnej metody):

mod = a % b
result = (a - mod) / b

Jeśli b był w rzeczywistości 0,2, a następnie {x0}} byłby 0, ale w punkcie zmiennoprzecinkowym jest nieco większy, więc mod wynosi tylko 0,2.

Jeśli robisz to ręcznie, możesz zobaczyć, jak skończymy z 59,0:

>>> a = 12.0
>>> b = 0.2
>>> mod = a % b
>>> mod
0.19999999999999934
>>> (a - mod) / b
59.0

OP również poprosi o błąd w podziale Pływające, oto to również:

Wartości (Mantissa * Base ^ Exponent):

12:         1.1000000000000000000000000000000000000000000000000000 * 2^3
0.2:        1.1001100110011001100110011001100110011001100110011010 * 2^(-3)

Pamiętaj, że 0,2 nie jest naprawdę 0,2, to 0,20000000000000001110223024626560423636680954236316680954236366808203123668082032366809542366809542363680954236368095423636265404123668095423636808203123166809542366809542366809542362680820312316680904125. Wynik podziału 12 o wartość, która jest i GT; 0,2 powinien być be & lt; 60.

Aby podzielić wartości, podzielamy Mantissa i odjąć wykładnik, więc otrzymujemy:

12 / 0.2:   0.1110111111111111111111111111111111111111111111111111111 * 2^6

Ale ostatnie 3 bitów nie pasują do podwójnego, który ma tylko 53 bitów dla Mantissa (w tym znaku) i obecnie używamy 56.

Ponieważ wynik rozpoczyna się od 0, najpierw znormalizujemy, pomnożyć Mantissa przez 2 i odejmując jedną z wykładnika. A potem musimy zaokrąglić do najbliższego 53-bitowego Mantissa:

normalised: 1.110111111111111111111111111111111111111111111111111111 * 2^5
rounded:    1.1110000000000000000000000000000000000000000000000000 * 2^5

1.11100000000000000000000000000000000000000000000000000000000000000000000 * 2 ^ 5 jest równe 60.

Różnica pomiędzy prawidłowym wynikiem ( 1.110111111111111111111111111111111111111111111111111111 * 2 ^ 5) i najbliższy wartości można reprezentują jako 64-bitowa podwójna (1,1110000000000000000000000000000000000000000000000000 * 2 ^ 5) jest błąd w zmiennoprzecinkowej podziału .

9
Diego Veralli 27 październik 2020, 07:37