Поясню: это не баг в общепринятом смысле (т.е. не ошибка программиста и не заскок конкретной программы). Это принципиально неустранимое ограничение любых компьютеров.
В математике, какие бы два сколь угодно близких числа мы не взяли, между ними всегда есть еще другие числа. Т.е. числовая ось непрерывна в любом масштабе. А в компьютере не так. Он в принципе работает с дискретными числами. И если наше вычисленное число попадает между этими дискретами, то оно округляется до ближайшего значения сетки дискретизации.
Числа одинарной (простой) точности с плавающей запятой, используемые в компьютерах, устроены так:
- нормализованная часть (ряд цифр, что стоит перед множителем 10в какой-то степени, называемой смещением) описывается 24-мя двоичными разрядами. Известно, что десять двоичных разрядов это ~ три десятичных, т.к. 210 ≈ 103. Поэтому 24 двоичных разряда, это примерно 7 десятичных.
- смещение (описывает степень в какую возводится множитель для нормализованной части) - 8 двоичных разрядов. Т.е. от 0 до 255. Имея в виду, что нам нужны и отрицательные степени, в двоичной системе множитель может быть в диапазоне от -127 до + 128. Продолжая иметь в виду, что 210 ≈ 103, получаем, что в десятичной системе смещение (т.е. степень десятки в множителе) будет от -38 до +38.
То есть, диапазон чисел простой точности ~ от 10-38 до 1038. Диапазон колоссальный. Но точность чисел в этом диапазоне oграничена 7...8 значащими десятичными цифрами.
Пример. У нас есть число a=16777216. И где-то в результате вычислений мы получаем число b=16777217. Но код этих чисел в компьютере будет совершенно одинаков! Потому что следующее число после 16777216, которое можно записать в виде числа одинарной точности будет 16777218. Дискрета равно двум цифрам последнего разряда. Все что между будет автоматически округлено до ближайшего возможного значения.
А теперь представьте, что в программе нам надо выполнить операцию 1/(b-a). Математически такая процедура допустима и даст внятный результат. Но у нас-то в компьютере получилось, что a=b (их коды одинаковы). И в знаменателе окажется 0. Программа вылетит с ошибкой деления на ноль.
Что-бы такие "подарки" случались пореже (но полностью их устранить невозможно принципиально) используются числа двойной точности с плавающей запятой (и в MMANA-GAL и в GAL-ANA используются именно такие). В них для нормализованной части числа отведены 53 бита. Это соответствует примерно 16 десятичным цифрам. Т.е. точность выше примерно в 109 раз. И во столько же раз ниже шанс нарваться на вышеописанную проблему. Но он никогда не исчезает.
Пример. У нас есть число 40 737 488 355 328 000. В компьютере это число будет записано как 64 битовая величина. Но точно такую же запись (т.е. значение) будет иметь и число 40 737 488 355 328 001. Эти числа для компьютера неотличимы..
Кроме более точного описания нормализованной части, в числах двойной точности отведено больше бит для описания смещения. Что дает совершенно фантастический диапазон чисел двойной точности от 10-302 до 10302 (сравните: в наблюдаемой части Вселенной не более 1087 элементарных частиц).
Числа двойной точности хотя и требуют больше ресурсов компьютера и большего времени вычислений, практически всегда дают точность гораздо выше реально требуемой. Исключения составляют задачи когда длиннющие числа должны совпадать до 15...17 разряда, а дискретизация приводит к их разнице (или наоборот, два числа отличаются на слишком малую величину, а дискретизация убивает эту разницу).
С числами одинарной точности проблема дискретизации встречается чаще. Например, если вы видели в результатах каких-то (не наших) вычислений результат 3,4999999 вместо 3,5 – это оно: слишком много знаков, шаг дискретизации представления чисел в компьютере оказался грубоват.