Тип double (IEEE 754, 64 бита) хранит число в научной записи, только по основанию 2: знак (1 бит), порядок (11 бит, со смещением 1023) и мантисса (52 бита, плюс неявная ведущая единица). Значение — (−1)^знак × 1.мантисса × 2^(порядок − 1023).
Конечной двоичной дробью записываются только числа вида k/2ⁿ: 0.5, 0.25, 0.375. А 0.1 = 1/10, и в знаменателе есть пятёрка — в двоичной системе получается бесконечная периодическая дробь 0.000110011001100… Её обрезают до 53 значащих бит, и хранится ближайшее представимое число — 0.1000000000000000055511… То же с 0.2. При сложении ошибки складываются, результат округляется до ближайшего double, и это не тот double, который получается из литерала 0.3.
Сколько точности. 53 бита — это 15–17 значащих десятичных цифр. Все целые до 2⁵³ (≈ 9·10¹⁵) представимы точно, дальше — уже через одно. У float 24 бита мантиссы — около 7 цифр, и 16 777 217 в него не помещается.
Сравнение. == для вычисленных значений почти всегда ошибка. Сравнивают с допуском: абсолютным abs(a - b) < 1e-9 для чисел около единицы или относительным, как math.isclose, для чисел любого масштаба.
Спецзначения. +∞ и −∞ (1.0 / 0 в Java), NaN (0.0 / 0, корень из −1) — и NaN не равен ничему, даже себе, поэтому проверяют isnan. Есть −0.0, равный +0.0, но 1 / −0.0 = −∞.
Последствия: порядок сложения меняет результат (сумма большого числа малых теряет точность — помогает алгоритм Кэхэна или math.fsum), деньги в double не хранят, счётчик цикла с шагом 0.1 не дойдёт ровно до 1.0.