c ++ std的inf是否与普通感觉无穷大完全相同

时间:2016-12-15 09:11:07

标签: c++ overflow std infinity

我正在实施一个相当复杂的数值算法。 它包含一些指数,其中我发现,在打印中间结果时,有一些溢出的双重。 但是,终端打印inf(不是InfNaN),它似乎不是双倍,甚至不是最小或最大可表达的双倍。 但似乎inf表现得好像它是扩展的实数系统(正负无穷大被认为是真数,而不是涉及限制的语句的缩写)。

我进行了测试:( g ++版:“Apple LLVM版本8.0.0(clang-800.0.42.1)”)

#include <iostream> // cout
#include <cmath> // exp, log
#include <limits> // data ranges

int main(void)
{
   const double dMin =std::numeric_limits<int>::min();
   const double dMax =std::numeric_limits<int>::max();
   double p1 =std::exp(710);
   double p2 =std::exp(750);
   double p3 =std::exp(800);
   double p4 =-std::log(0.0);
   std::cout << "p1 :=std::exp(710) =" << p1 << '\n';
   std::cout << "p2 :=std::exp(750) =" << p2 << '\n';
   std::cout << "p3 :=std::exp(800) =" << p3 << '\n';
   std::cout << "p4 :=-std::log(0.0) =" << p4 << '\n';
   std::cout << "does p1==dMax? " << ( (p1==dMax) ? "yes" : "no" ) << '\n';
   std::cout << "does p1==-dMin? " << ( (p1==-dMin) ? "yes" : "no" ) << '\n';
   std::cout << "does p1==p2? " << ( (p1==p2) ? "yes" : "no" ) << '\n';
   std::cout << "does p2==p3? " << ( (p2==p3) ? "yes" : "no" ) << '\n';
   std::cout << "does p3==p4? " << ( (p3==p4) ? "yes" : "no" ) << '\n';
   std::cout << "does 3*p1==p2/2+1? " << ( (3*p1==p2/2+1) ? "yes" : "no" ) << '\n';
   std::cout << "does (-p1)*(-p2)==p3*p3*p3? " << ( ((-p1)*(-p2)==p3*p3*p3) ? "yes" : "no" ) << '\n';
   std::cout << "does std::log(p2)==std::exp(p3)? " << ( (std::log(p2)==std::exp(p3)) ? "yes" : "no" ) << '\n';
}

输出:

p1 :=std::exp(710) =inf
p2 :=std::exp(750) =inf
p3 :=std::exp(800) =inf
p4 :=-std::log(0.0) =inf
does p1==dMax? no
does p1==-dMin? no
does p1==p2? yes
does p2==p3? yes
does p3==p4? yes
does 3*p1==p2/2+1? yes
does (-p1)*(-p2)==p3*p3*p3? yes
does std::log(p2)==std::exp(p3)? yes

似乎inf确实类似于我们的无穷大概念,但不等于std的最大值和最小值。

那么,假设inf的工作方式与普通感觉无限相同,是否安全? 我是否可以依赖算法的中间步骤中的操作,该算法涉及inf,将其视为真正的无限,并且最终只处理其结果? 或者如果没有,我应该抓住它吗?但我怎么能,因为它不是最大或最小的双倍?

3 个答案:

答案 0 :(得分:2)

限制对IEEE754浮点的答案,+ Inf来自1.0 / 0.0之类的计算,而-Inf来自-1.0 / 0.0

另一种类型NaN(不是数字)来自0.0 / 0.0

设置为+Inf的两个浮点变量将true相互比较,同上-Inf。它们代表std::numeric_limits<double>::max()的不同数量。 +Inf大于除自身和NaN之外的所有值。

请注意,设置为NaN的两个浮点变量将true相互比较,或与其他任何内容进行比较。

(对于它的价值,std::log(0.0) 必须返回-Inf,而不是NaN)。见http://en.cppreference.com/w/cpp/numeric/math/log

答案 1 :(得分:2)

正如其他答案已经提到的那样,标准没有很好地定义浮点数的行为,但它由IEC-559/IEEE-754很好地定义,并且大多数实现使用它。首先要做的是检查您的实现是否有效地使用它:

static_assert(std::numeric_limits<double>::is_iec559, "Stupid implementation!");

一旦你通过了这个断言,事情变得容易多了!首先,您可以使用以下实用程序函数来获取 true 无穷大(您不需要is_iec559才能使其真正起作用...):

std::numeric_limits<double>::infinity()

更好的是,IEEE-754对无穷大的行为有非常明确的规则: http://steve.hollasch.net/cgindex/coding/ieeefloat.html#operations 1 ,例如-inf * -inf = +inf+inf + +inf = +Inf,依此类推。标准数学函数也具有明确定义的无限行为,因此您也可以依赖它们。

因此,如果您的实施符合IEEE标准,,您可以依赖无穷大的中间操作,只检查最终结果。

1 这不是官方资源,但据我所知,这是正确的。

答案 2 :(得分:1)

  

c ++ std&#39; s ...

C ++标准没有规定无限行为的任何要求 - 或者无穷大可以用浮点数表示。

如果您的系统使用符合特定浮点标准的浮点数,那么该标准可能会指定无穷大的行为。

  

似乎inf确实类似于我们的无穷大概念,但不等于std的最大值和最小值。

事实上。 numeric_limits::max()定义为返回最大有限值。

  

如何[到捕获无穷大],因为它不是最大值或最小值?

如果通过 catch 表示您希望检查某个值是否为无穷大,则可以与numeric_limits::infinity()进行比较,或者如果您有C ++ 11,那么{{1} }(检查正无穷大)。