何时发生下溢? [英] When does underflow occur?

查看:13
本文介绍了何时发生下溢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到计算 1.77e-308/10 会触发下溢异常的情况,但计算 1.777e-308/10 不会.这很奇怪,因为:

I get into a situation where calculating 1.77e-308/10 triggers an underflow exception, but calculating 1.777e-308/10 does not. This is strange because:

下溢发生在浮点的真实结果时操作在幅度上小于(即更接近于零)比可表示为正常浮点数的最小值目标数据类型(来自算术下溢,维基百科)

Underflow occurs when the true result of a floating point operation is smaller in magnitude (that is, closer to zero) than the smallest value representable as a normal floating point number in the target datatype (from Arithmetic Underflow, Wikipedia)

换句话说,如果我们计算 x/y,其中 xy 都是 double,那么如果 0 <会发生下溢.|x/y|<2.2251e-308(最小正归一化double2.2251e-308).因此,理论上,1.77e-308/101.777e-308/10 都应该触发下溢异常.该理论与我用下面的 C 程序测试的结果相矛盾.

In other words, if we calculate x/y where both x and y are double, then underflow should occur if 0 < |x/y| < 2.2251e-308 (the smallest positive normalized double is 2.2251e-308). In theory, therefore, both 1.77e-308/10 and 1.777e-308/10 should trigger an underflow exception. The theory contradicts with what I have tested with the C program below.

#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
");
  }
  else puts("No underflow
");
}

为了编译程序,我使用了 gcc program.c -lm;我也尝试了 Clang,它给了我相同的结果.有什么解释吗?

To compile the program, I used gcc program.c -lm; I also tried Clang, which gave me the same result. Any explanation?

我已经通过 这个在线 IDE 分享了上面的代码.

I have shared the code above via this online IDE.

推荐答案

下溢不仅仅是范围的问题,还有精度/舍入的问题.

Underflow is not only a question of range, but also of precision/rounding.

7.12.1 错误情况的处理
如果数学结果的量级太小以至于在指定类型的对象中无法在没有异常舍入误差的情况下表示数学结果,则结果下溢.C11 §7.12.1 6

7.12.1 Treatment of error conditions
The result underflows if the magnitude of the mathematical result is so small that the mathematical result cannot be represented, without extraordinary roundoff error, in an object of the specified type. C11 §7.12.1 6

1.777e-308,转换为最近的 binary64 0x1.98e566222bcfcp-1023 恰好有一个有效数字 (0x198E566222BCFC, 7193376082541820) 是 10 的倍数.因此除以 10 是精确的.没有舍入误差.

1.777e-308, converted to the nearest binary64 0x1.98e566222bcfcp-1023, happens to have a significand (0x198E566222BCFC, 7193376082541820) that is a multiple of 10. So dividing by 10 is exact. No roundoff error.

我发现使用十六进制表示法更容易演示.请注意,除最小值外,除以 2 始终是精确的.

I find this easier to demo with hex notation. Note that dividing by 2 is always exact, except for the smallest value.

#include <float.h>
#include <stdio.h>
#include <fenv.h>
#include <math.h>

int uf_test(double x, double denominator){
  printf("%.17e %24a ", x, x);
  feclearexcept(FE_ALL_EXCEPT);
  double y=x/denominator;
  int uf = !!fetestexcept(FE_UNDERFLOW);
  printf("%-24a %s
", y, uf ? "Underflow" : "");
  return uf;
}

int main(void) {
  uf_test(DBL_MIN, 2.0);
  uf_test(1.777e-308, 2.0);
  uf_test(1.77e-308, 2.0);
  uf_test(DBL_TRUE_MIN, 2.0);

  uf_test(pow(2.0, -1000), 10.0);
  uf_test(DBL_MIN, 10.0);
  uf_test(1.777e-308, 10.0);
  uf_test(1.77e-308, 10.0);
  uf_test(DBL_TRUE_MIN, 10.0);
  return 0;
}

输出

2.22507385850720138e-308                0x1p-1022 0x1p-1023                
1.77700000000000015e-308  0x1.98e566222bcfcp-1023 0x1.98e566222bcfcp-1024  
1.77000000000000003e-308  0x1.97490d21e478cp-1023 0x1.97490d21e478cp-1024  
4.94065645841246544e-324                0x1p-1074 0x0p+0                   Underflow

// No underflow as inexact result is not too small
9.33263618503218879e-302                0x1p-1000 0x1.999999999999ap-1004  
// Underflow as result is too small and inexact
2.22507385850720138e-308                0x1p-1022 0x1.99999999999ap-1026   Underflow
// No underflow as result is exact
1.77700000000000015e-308  0x1.98e566222bcfcp-1023 0x1.471deb4e8973p-1026   
1.77000000000000003e-308  0x1.97490d21e478cp-1023 0x1.45d40a818394p-1026   Underflow
4.94065645841246544e-324                0x1p-1074 0x0p+0                   Underflow

这篇关于何时发生下溢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆