0.2 не является числом с плавающей запятой двойной точности, поэтому оно округляется до ближайшего числа двойной точности, которое:
0.200000000000000011102230246251565404236316680908203125
Это довольно громоздко, поэтому давайте посмотрим на это в шестнадцатеричном виде:
0x0.33333333333334
Теперь давайте посмотрим, что происходит, когда это значение многократно вычитается из 1,0:
0x1.00000000000000
- 0x0.33333333333334
--------------------
0x0.cccccccccccccc
Точный результат не представляется в двойной точности, поэтому он округляется, что дает:
0x0.ccccccccccccd
В десятичном виде это точно:
0.8000000000000000444089209850062616169452667236328125
Теперь мы повторим процесс:
0x0.ccccccccccccd
- 0x0.33333333333334
--------------------
0x0.9999999999999c
rounds to 0x0.999999999999a
(0.600000000000000088817841970012523233890533447265625 in decimal)
0x0.999999999999a
- 0x0.33333333333334
--------------------
0x0.6666666666666c
rounds to 0x0.6666666666666c
(0.400000000000000077715611723760957829654216766357421875 in decimal)
0x0.6666666666666c
- 0x0.33333333333334
--------------------
0x0.33333333333338
rounds to 0x0.33333333333338
(0.20000000000000006661338147750939242541790008544921875 in decimal)
0x0.33333333333338
- 0x0.33333333333334
--------------------
0x0.00000000000004
rounds to 0x0.00000000000004
(0.000000000000000055511151231257827021181583404541015625 in decimal)
Таким образом, мы видим, что накопленное округление, требуемое арифметикой с плавающей запятой, дает очень маленький ненулевой результат, который вы наблюдаете. Округление является тонким, но оно детерминированное, а не волшебство и не ошибка. Стоит потратить время на изучение.