【问题标题】:How to handle floating-point underflow?如何处理浮点下溢?
【发布时间】:2013-07-10 17:36:14
【问题描述】:

我正在尝试理解 C++ 数值属性。因此,我对下溢现象很感兴趣。谁能给我一个下溢的例子以及如何处理它?

【问题讨论】:

  • 0U-1。但是,通过放置 UB 标记,我假设您的意思是有符号下溢。
  • @chris(我们假设 32 位无符号)从技术上讲,那里没有下溢/溢出:0U-1 的结果是 4294967295,而不是 -1。 4294967295 适合 32 位无符号整数,因此不会溢出。相比之下,-2147483648-1 的结果是 -2147483649,它不适合有符号的 32 位 int,因此会上溢/下溢。
  • @R.MartinhoFernandes,我知道我应该输入那些多余的字符,即使我很懒,只是使用了INT_MIN。无论哪种方式都可能少于我必须标记的注释。这有点令人沮丧。
  • 使用“numerical”让我觉得问题是关于浮点下溢,这不是未定义的行为(因为编译器选择提供 IEEE 754 浮点语义)。
  • @PascalCuoq 它是关于双下溢

标签: c++ floating-point underflow


【解决方案1】:
int main()
{
        short int x ;

        for(x=0;;x++)
        {
                printf("%d \n",x);

                if(x < 0)
                  break;
        }
}

o/p

---
---
--
32761
32762
32763
32764
32765
32766
32767
-32768

假设您要在签名号中询问下溢概念。这里的概念是签名的 no 就像一个圆圈,一旦你到达圆圈的一半,它将进入该圆圈的 -ve 一半,它将继续并且永远不会结束。它开始于0-32767 (+ve) -32768 to -1 (-ve) half.

这是程序员处理这种情况的责任。如果您下溢,编译器不会引发任何错误。

希望这会有所帮助。

【讨论】:

  • “这里的概念是签名的 no 就像一个圆圈,一旦你到达圆圈的一半,它将进入该圆圈的 -ve 一半,它将继续并且永远不会结束。”不是真的,不。通常,如果操作的结果不能以给定的类型表示(例如在您的示例中,16 位有符号整数上的数字 32768),则行为是未定义的。
  • 作为 UB,编译器可以根据需要引发错误。
  • 使用双精度值怎么样?
  • @R.MartinhoFernandes,Mysticial 的问题是我在说这很重要时唯一想到的问题 :) 我可能把“什么都不说”理解得太字面意思了,但是 如果在对表达式求值,结果未在数学上定义或不在其类型的可表示值范围内,行为未定义。
  • @R.MartinhoFernandes 问题中的程序不会在大多数编译平台上调用未定义的行为,因为x++ 被评估为x = (short)((int)x + 1);。它仅在转换为 short 时调用实现定义的行为。查看blog.frama-c.com/index.php?post/2013/07/11/…的问答部分
【解决方案2】:

浮点下溢的一个例子是:

double d = DBL_MIN / 3.0;

符合 IEEE 754 标准的实现应将 d 设置为“subnormal”,即一个非常接近于零以致精度降低的数字。您会在Wikipedia 上找到大量信息。

某些实现可能会“清零”。上例中的结果是将d 设置为零。

下溢是无法使用较大的负指数来表示数字的结果。有时可以通过“标准化”计算来避免它们,这相当于以某种方式计算 x1*2N, x2* 2N, ... 而不是 x1, x2, ... 用于您选择的 N。

浮点下溢不是未定义的行为。如果您愿意,可以使用“FPU 异常”通过轮询或接收 SIGFPE 来检测它。请注意,“FPU 异常”与 C++ 异常除了名称之外没有任何共同之处。

【讨论】:

  • 还有其他可能导致下溢的操作吗?
  • @WildThing 除了 sqrt(即 +、-、*、/)之外的所有 5 个基本 IEEE 754 操作都可能导致下溢。每次数学结果介于 -DBL_MIN*(1-DBL_EPSILON/4)DBL_MIN*(1-DBL_EPSILON/4) 之间时,它们都会导致下溢(给出或占用 ULP 的一小部分)。
  • @WildThing 对于这些函数的合理实现,规则“每次数学结果介于……之间时它们都会导致下溢”适用。例如,次正规的正弦是次正规的。浮点的性质(很可能)意味着没有正常的双精度数 x 这样 sin(x)cos(x) 是次正常的,但这是假设一个理智的实现。
  • FPU 异常与 C++ 异常没有任何共同之处:但似乎我们可以在某些操作系统上连接它们stackoverflow.com/questions/2769814/…(虽然我没有尝试)
  • 虽然DBL_MIN/2 下溢,但如果启用默认下溢处理,则此下溢将被解除(未标记并且实际上永远不存在),因为结果是准确的。在默认模式下,精确的结果永远不会下溢。相反,DBL_MIN/3DBL_MIN/(2./3) 总是会引发下溢标志。
猜你喜欢
  • 1970-01-01
  • 2023-03-04
  • 2016-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-12
  • 2020-02-19
  • 2020-09-06
相关资源
最近更新 更多