Я попадаю в ситуацию, когда вычисление 1.77e-308/10
вызывает исключение потери значимости, а вычисление 1.777e-308/10
— нет. Это странно, потому что:
Потеря значимости происходит, когда истинный результат операции с плавающей запятой меньше по величине (то есть ближе к нулю), чем наименьшее значение, представленное как обычное число с плавающей запятой в целевом типе данных (из Arithmetic Underflow, Википедия)
Другими словами, если мы вычислим x/y
, где и x
, и y
равны double
, то потеря значимости должна произойти, если 0 < |x/y| < 2.2251e-308
(наименьшее положительное нормализованное double
равно 2.2251e-308
). Таким образом, теоретически и 1.77e-308/10
, и 1.777e-308/10
должны вызывать исключение потери значимости. Теория противоречит тому, что я проверил с помощью программы C ниже.
#include <stdio.h>
#include <fenv.h>
#include <math.h>
int main(){
double x,y;
// x = 1.77e-308 => underflow
// x = 1.777e-308 gives ==> no underflow
x=1.77e-308;
feclearexcept(FE_ALL_EXCEPT);
y=x/10.0;
if (fetestexcept(FE_UNDERFLOW)) {
puts("Underflow\n");
}
else puts("No underflow\n");
}
Для компиляции программы я использовал gcc program.c -lm
; Я также попробовал Clang, который дал мне тот же результат. Любое объяснение?
[Редактировать] Я поделился приведенным выше кодом через эту онлайн-среду разработки.
1.77e-308
вызывает недополнение, а 1.777e-308;` - нет.g++ (Debian 4.9.2-10) 4.9.2
- person LPs   schedule 16.02.2017gcc
: все то же самое на моей платформе. АDBL_MIN
это2.2251e-308
. - person LPs   schedule 16.02.2017