(Uwaga: dołączę „b”, aby wskazać tutaj liczby binarne. Wszystkie pozostałe liczby są podawane dziesiętnie)
Jednym ze sposobów myślenia o różnych rzeczach jest zapis naukowy. Przyzwyczailiśmy się widzieć liczby wyrażone w notacji naukowej, np. 6.022141 * 10 ^ 23. Liczby zmiennoprzecinkowe są przechowywane wewnętrznie w podobnym formacie - mantysa i wykładnik, ale przy użyciu potęg dwóch zamiast dziesięciu.
Twoje 61.0 może zostać przepisane jako 1.90625 * 2 ^ 5 lub 1.11101b * 2 ^ 101b z mantysą i wykładnikami potęgi. Aby pomnożyć to przez dziesięć i (przesunąć przecinek dziesiętny), możemy:
(1,90625 * 2 ^ 5) * (1,25 * 2 ^ 3) = (2,3828125 * 2 ^ 8) = (1,19140625 * 2 ^ 9)
lub z mantysą i wykładnikami w formacie binarnym:
(1,11101b * 2 ^ 101b) * (1,01b * 2 ^ 11b) = (10,0110001b * 2 ^ 1000b) = (1,00110001b * 2 ^ 1001b)
Zwróć uwagę na to, co zrobiliśmy, aby pomnożyć liczby. Pomnożymy mantysy i dodamy wykładniki. Następnie, ponieważ mantysa zakończyła się na więcej niż dwa, znormalizowaliśmy wynik, podnosząc wykładnik potęgi. To tak, jakbyśmy korygowali wykładnik po wykonaniu operacji na liczbach w dziesiętnej notacji naukowej. W każdym przypadku wartości, z którymi pracowaliśmy, miały skończoną reprezentację w formacie binarnym, a zatem wartości generowane przez podstawowe operacje mnożenia i dodawania również generowały wartości o skończonej reprezentacji.
Zastanówmy się teraz, jak podzielimy 61 przez 10. Zaczniemy od podzielenia mantysy, 1.90625 i 1.25. W ułamku dziesiętnym daje to 1,525 ładną krótką liczbę. Ale co to jest, jeśli przekonwertujemy go na binarny? Zrobimy to w zwykły sposób - odejmując największą możliwą potęgę dwóch, gdy tylko jest to możliwe, podobnie jak przekształcanie liczb całkowitych dziesiętnych na binarne, ale użyjemy ujemnych potęg dwóch:
1,525 - 1 * 2 ^ 0 -> 1
0,525 - 1 * 2 ^ -1 -> 1
0,025 - 0 * 2 ^ -2 -> 0
0,025 - 0 * 2 ^ -3 -> 0
0,025 - 0 * 2 ^ -4 -> 0
0,025 - 0 * 2 ^ -5 -> 0
0,025 - 1 * 2 ^ -6 -> 1
0,009375 - 1 * 2 ^ -7 -> 1
0,0015625 - 0 * 2 ^ -8 -> 0
0,0015625 - 0 * 2 ^ -9 -> 0
0,0015625 - 1 * 2 ^ -10 -> 1
0,0005859375 - 1 * 2 ^ -11 -> 1
0,00009765625 ...
O o. Teraz mamy kłopoty. Okazuje się, że 1,90625 / 1,25 = 1,525, jest ułamkiem powtarzalnym wyrażonym binarnie: 1.11101b / 1.01b = 1.10000110011 ... b Nasze maszyny mają tylko tyle bitów, aby utrzymać tę mantysę, więc zaokrągli ułamek i zakładamy zera powyżej pewnego punktu. Błąd, który widzisz, dzieląc 61 przez 10, jest różnicą między:
1.100001100110011001100110011001100110011 ... b * 2 ^ 10b
i, powiedzmy:
1.100001100110011001100110b * 2 ^ 10b
To zaokrąglenie mantysy prowadzi do utraty precyzji, którą kojarzymy z wartościami zmiennoprzecinkowymi. Nawet jeśli mantysę można wyrazić dokładnie (np. Po prostu dodając dwie liczby), nadal możemy uzyskać utratę liczbową, jeśli mantysa potrzebuje zbyt wielu cyfr, aby zmieścić się po normalizowaniu wykładnika.
W rzeczywistości robimy takie rzeczy przez cały czas, gdy zaokrąglamy liczby dziesiętne do rozsądnego rozmiaru i po prostu podajemy kilka pierwszych cyfr. Ponieważ wynik wyrażamy w postaci dziesiętnej, wydaje się to naturalne. Ale jeśli zaokrąglimy liczbę dziesiętną, a następnie przekonwertujemy ją na inną podstawę, wyglądałby tak samo brzydko, jak liczby dziesiętne, które otrzymujemy z powodu zaokrąglania zmiennoprzecinkowego.