Jak Lua obsługuje liczby całkowite i zmiennoprzecinkowe?


11

O ile pamiętam siebie programowania, nauczono mnie, aby nie porównywać liczb zmiennoprzecinkowych dla równości. Teraz, czytając Programowanie w Lua o numbertypie Lua , znalazłem:

Typ liczby reprezentuje liczby rzeczywiste (zmiennoprzecinkowe podwójnej precyzji). Lua nie ma typu liczby całkowitej, ponieważ nie potrzebuje go. Istnieje powszechne nieporozumienie dotyczące błędów arytmetycznych zmiennoprzecinkowych, a niektórzy obawiają się, że nawet zwykły przyrost może być dziwny w przypadku liczb zmiennoprzecinkowych. Faktem jest, że kiedy używasz podwójnego do reprezentowania liczby całkowitej, nie ma w ogóle błędu zaokrąglania (chyba że liczba jest większa niż 100 000 000 000 000). W szczególności liczba Lua może reprezentować dowolną długą liczbę całkowitą bez problemów z zaokrąglaniem. Co więcej, większość współczesnych procesorów wykonuje arytmetykę zmiennoprzecinkową tak szybko jak (lub nawet szybciej niż).

Czy to prawda dla wszystkich języków? Zasadniczo, jeśli nie przekroczymy liczby zmiennoprzecinkowej w liczbach podwójnych, jesteśmy bezpieczni w arytmetyce liczb całkowitych? Lub, aby być bardziej zgodnym z tytułem pytania, czy jest coś specjalnego, co Lua robi ze swoim numbertypem, więc działa dobrze zarówno jako liczba całkowita, jak i liczba zmiennoprzecinkowa?



@JoonasPulakka dzięki, to całkiem cenny dodatek.
Petr Abdulin

Odpowiedzi:


11

Lua twierdzi, że liczby zmiennoprzecinkowe mogą reprezentować liczby całkowite tak dokładnie, jak typy całkowite, i jestem skłonny się zgodzić. Nie ma nieprecyzyjnej reprezentacji ułamkowej części liczbowej, z którą trzeba sobie poradzić. Niezależnie od tego, czy przechowujesz liczbę całkowitą w typie całkowitym, czy przechowujesz ją w mantysie liczby zmiennoprzecinkowej, wynik jest taki sam: ta liczba całkowita może być dokładnie reprezentowana, o ile nie przekroczysz liczby bitów w mantysie , + 1 bit w wykładniku wykładniczym.

Oczywiście, jeśli spróbujesz zapisać rzeczywistą liczbę zmiennoprzecinkową (np. 12.345) w reprezentacji zmiennoprzecinkowej, wszystkie zakłady są wyłączone, więc twój program musi być jasny, że liczba jest naprawdę prawdziwą liczbą całkowitą, która nie przepełnia mantysa, aby traktować ją jak rzeczywistą liczbę całkowitą (tj. w odniesieniu do porównywania równości).

Jeśli potrzebujesz większej liczby całkowitej niż precyzja, zawsze możesz zastosować bibliotekę o dowolnej precyzji .

Dalsza lektura
Jaka jest maksymalna wartość liczby w Lua?


Co z ich drugim argumentem, tj. Że zmiennoprzecinkowa jest tak szybka lub szybsza niż arytmetyka liczb całkowitych we współczesnych procesorach? Wydaje mi się to wątpliwe, nawet jeśli używam liczb zmiennoprzecinkowych do wykonywania arytmetyki liczb całkowitych.
Andres F.,

2
@AndresF. Nie rozumiem, jak to jest szybsze, chyba że eliminujesz rzut za pomocą jednego typu liczbowego zamiast dwóch.
Robert Harvey

Zgoda. To nie ma dla mnie żadnego sensu. Zastanawiam się, czy to zostało wyjęte z kontekstu ...
Andres F.,

1
Wystarczająco duże liczby całkowite nie mogą być przechowywane dokładnie w obiekcie zmiennoprzecinkowym. 64-bit doublema około 51 bitów mantysy; nieparzyste liczby całkowite większe niż około 2 ** 51 będą miały błędy zaokrąglania. 64-bitowa liczba całkowita może dokładnie przechowywać większe wartości całkowite, ponieważ nie poświęca żadnych bitów wykładnikowi potęgowemu.
Keith Thompson

@KeithThompson: Myślałem, że sugeruje to moja odpowiedź, kiedy powiedziałem „przechowywany w mantysie”. Jednak zmienię odpowiedź, aby wyjaśnić.
Robert Harvey

6

Podwójne są przechowywane jako mantysa i wykładnik potęgi. Zobacz format, aby uzyskać więcej informacji. Zasadniczo wszystkie liczby mają postać: wykładnik mantysy * 2 . Dla dowolnej liczby całkowitej mniejszej niż 2 52 wykładnik będzie wynosił zero, dzięki czemu mantysa bit po bicie będzie równoważna 52-bitowej liczbie całkowitej bez znaku. Osobny bit znaku służy do wskazania liczb ujemnych.

W rzeczywistości, nawet niektóre liczby całkowite większe niż 2 52 mogą być reprezentowane dokładnie, tak długo, jak wszystkie cyfry obok 52 nd są zerami. Ponadto niektóre ułamki, takie jak 0,5, można dokładnie przedstawić. Tylko wtedy, gdy ułamek ciągle powtarza się (jak 1/3) w bazie 2 lub w inny sposób wymaga zbyt wielu bitów poza punkt rzutu, tracisz precyzję.


Nie wynika to z ciągłego powtarzania miejsc po przecinku. Jest tak, ponieważ wielu liczb dziesiętnych (dziesięciu podstawowych) nie można przedstawić dokładnie jako potęgę dwóch.
Robert Harvey

3
W bazie 2 liczby, których nie można dokładnie przedstawić, będą się ciągle powtarzać. Na przykład 0,1 dziesiętna staje się 0,0 (0011) w systemie binarnym, a 0011 ciągle się powtarza.
Karl Bielefeldt

3
Tak, dokładnie. Ale nie powtarzanie w bazie 10. Powtarzanie w bazie 2.
Robert Harvey
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.