С http://www.strw.leidenuniv.nl/docs/intel/f_ug/ieee_ovw.htm
Исключение недостаточного значения возникает, если округленный результат имеет показатель степени
это слишком мало, чтобы быть представленным с использованием формата с плавающей запятой
результат.
Это означает, что ошибка возникает, когда отношение делимого и делителя достаточно мало, чтобы превышать точность формата с плавающей запятой, а не какую-либо зависимость от конкретного значения, такого как эпсилон.
Когда знаменатель приближается к нулю, предполагая ненулевой числитель, результат деления будет приближаться к бесконечности. Когда числитель приближается к нулю, предполагая ненулевой знаменатель, результат приближается к нулю. Когда это значение становится достаточно маленьким, возникает событие.
Если числитель и знаменатель очень близки по значению, даже если они очень малы, вы можете получить полезный результат, поэтому очень маленький числитель не обязательно вызывает понижение.
Пример
В C # эпсилон равен 1,401298E-45.
эпсилон / эпсилон == 1,0f
Несмотря на то, что числитель очень и очень маленький, результат все еще является действительным числом с плавающей точкой.
Теперь, если вы попробуете что-то вроде этого:
float max = 3.40282347E+38f;
/// underflow, denominator will be 0.0f
float denominator = epsilon / max;
denominator
будет иметь порядок 1e-83. Поскольку 83 намного превышает максимальный показатель с плавающей запятой одинарной точности, значение будет ограничено до нуля. Это место, где происходит недостаточное заполнение.
/// generates a divide-by-zero error.
float result = 10 / denominator;
Это генерирует деление на ноль вместо бесконечности, потому что промежуточный результат, сохраненный в denominator
, сначала фиксируется на 0 перед использованием во второй операции.
Независимо от того, получаете ли вы недополнение или деление на ноль, зависит от компилятора, вашего использования и порядка скобок и т. Д.
Например, снова в C #:
10f / float.Epsilon / float.MaxValue
а также
(10f / float.Epsilon) / float.MaxValue
дает 20971522.0f.
Тем не менее, математически эквивалентное выражение:
10f / (float.Epsilon / float.MaxValue)
дает Бесконечность.