Мы дошли до вопроса из начала урока. Попробуем перевести 0,1 в двоичную дробь.
Алгоритм обратный тому, что был в уроке 2.5 для целых чисел: там мы делили на основание и собирали остатки, здесь дробную часть надо умножать на 2 и собирать целые части.
Целая часть произведения на каждом шаге и есть очередной бит, а в работу идёт то, что осталось после запятой:
| Умножаем |
Получаем |
Бит |
Остаётся |
| $0{,}1 \cdot 2$ |
$0{,}2$ |
0 |
$0{,}2$ |
| $0{,}2 \cdot 2$ |
$0{,}4$ |
0 |
$0{,}4$ |
| $0{,}4 \cdot 2$ |
$0{,}8$ |
0 |
$0{,}8$ |
| $0{,}8 \cdot 2$ |
$1{,}6$ |
1 |
$0{,}6$ |
| $0{,}6 \cdot 2$ |
$1{,}2$ |
1 |
$0{,}2$ |
| $0{,}2 \cdot 2$ |
$0{,}4$ |
0 |
$0{,}4$ |
Последняя строка повторяет вторую: дробная часть вернулась к прежнему значению – значит, дальше всё повторится, и повторяться будет вечно:
$0{,}1_{10}$ = 0,0001100110011001100…₂ – период 0011 без конца.
Причина ровно та, о которой мы говорили после формулы: 0,1 = 1/10, а $10 = 2 \cdot 5$. Множитель 5 в знаменателе не сводится к степеням двойки, поэтому конечной двоичной записи у одной десятой нет.
И здесь стоит остановиться, потому что это не «баг компьютера». Ровно то же самое происходит в привычной десятичной системе: 1/3 = 0,333… – и никого это не смущает, мы просто знаем, что три в знаменателе «не дружит» с десяткой. У двоичной системы свой список неудобных знаменателей, и десятка в нём есть. Дроби вроде 0,5 или 0,25 записываются идеально, а самая бытовая на вид 0,1 – нет.
Мантисса хранит 52 бита, значит бесконечную последовательность приходится обрубить и округлить. В памяти вместо 0,1 оказывается ближайшее представимое число – очень близкое, но не равное.
Ниже тот же алгоритм пошагово. Прокрутите трассировку до шага, где переменная num снова становится равна 2, и сравните с первой итерацией. Как только состояние повторилось, дальнейшее поведение цикла предопределено – этим и доказывают, что дробь бесконечна.