/ / Python: Dlaczego przybliżenia są dziesiętne? - python-3.4

Python: Dlaczego przybliżenia są przybliżone? - python-3.4

Eksperymentowałem z powłoką IDLE Python 3.4.0 i wykonałem poniższy kod.

>>> from decimal import *
>>> getcontext().prec = 500
>>> e = Decimal(2.4)
>>> print(e)
2.399999999999999911182158029987476766109466552734375

Jak widzisz, ustawiam zmienną e równa dokładnie 2.4, nic więcej, nic mniej. Jednak kiedy drukowałem e, zamiast drukowania 2.4 lub 2.400000..., wydrukowało to, co widzisz powyżej. Próbowałem wtedy zmienić getcontext().prec do 5, i nadal drukowane dokładnie takie same wyniki. Teraz, aby powtórzyć mój eksperyment, przetestowałem go podając liczbę całkowitą, a następnie inną liczbę dziesiętną.

>>> f = Decimal(10)
>>> print(f)
10
>>> g = Decimal(10.1)
>>> print(g)
10.0999999999999996447286321199499070644378662109375

Dziwny ciąg liczb dziesiętnych jest drukowany tylko wtedy, gdy przypiszę niecałkowitą liczbę z klasą dziesiętną. W końcu przetestowałem to z liczbami zmiennoprzecinkowymi.

>>> h = float(2.4)
>>> print(h)
2.4
>>> i = float(10.1)
>>> print(i)
10.1

Dlaczego klasa dziesiętna powoduje te dziwne ciągi liczb dziesiętnych zamiast dokładnej liczby?

Odpowiedzi:

1 dla odpowiedzi № 1

Nie musi to mieć nic wspólnego z Pythonem, jest to po prostu sposób, w jaki komputery obsługują arytmetykę zmiennoprzecinkową.

Udawaj, że próbujesz dokładnie zapisać 1/3jako dziesiętne w podstawie 10 - nie możesz mieć nieskończonej ilości czasu lub papieru. (0.333333 ...) Istnieje nieskończona liczba 3s, więc każda reprezentacja dziesiętna może być jedynie przybliżeniem.

Podobnie, komputery nie mogą reprezentować niektórychfrakcje z doskonałą precyzją. (ponieważ nie mają nieskończonej pamięci), więc w tym przypadku najbliższy komputer może dostać się do 10.1 to 10.0999999999999996447286321199499070644378662109375. Nie ma to związku z getcontext() lub jakikolwiek inny, ponieważ komputer nie może przechowywać dokładnie 10,1 lub 2.4.


2 dla odpowiedzi nr 2

Kiedy przejdziesz literał 2.4 do dziesiętnego, tworzysz Decimal z pływaka 2.4. Wartość float jest już przybliżona i nie ma takiej możliwości Decimal aby odzyskać tę "dokładność".

Aby utworzyć dokładnie dziesiętny (2.4), możesz zamiast tego podać ciąg znaków

>>> from decimal import *
>>> getcontext().prec = 500
>>> e = Decimal("2.4")
>>> e
Decimal("2.4")

lub użyj podziału na wartości dziesiętnej uzyskanej z liczby całkowitej

>>> Decimal(24)/10
Decimal("2.4")