即使使用 -ffast-math 优化,exp(-1/0.) == 0 也一定能成立吗?

Posted

技术标签:

【中文标题】即使使用 -ffast-math 优化,exp(-1/0.) == 0 也一定能成立吗?【英文标题】:Is exp(-1/0.) == 0 sure to hold even with -ffast-math optimisations? 【发布时间】:2018-05-17 10:56:35 【问题描述】:

根据 IEEE-754,以下

#include <iostream>
#include <cmath>

int main() 
  std::cout << std::exp(-1/0.) << "\n";
  return 0;

产生0 作为结果。原因是,-1/0.0 给出了-INF,而其中的exp 给出了0

现在,我需要使用-ffast-math 运行我的代码。我了解此选项makes, in particular, infinities non-IEEE-conformant。所以,我认为我不能依赖中间的 -INF 结果。

但是,对于负参数,指数函数(至少在数学上)非常稳定:任何 有限&lt; -1e+3 已经产生 0 作为结果。所以,如果编译器只是用一个大的有限值替换无穷大,我会完全没问题。

至少在g++-5.4 中,这似乎工作可靠,但依赖它是否谨慎?


我还没有被 cmets 说服,并回答说原始代码不可靠,但我决定采用以下方法来确定:

#include <iostream>
#include <cmath>
#include <limits>

int main() 
  double a = 0.;   // In practice, this is actually a small, nonnegative,
                   // usually-but-not-always >0 number
  double tiny = 1e-50;
  double b = std::exp(-1/(a+tiny));
  std::cout << b << "\n";
  return 0;

这很丑陋,但它确保除数始终大于零,同时避免任何条件。

我考虑过使用epsilon 而不是tiny,但它并不能更好地表达意图。 (事实上​​,它会扭曲结果;我真正想要表达的是 a + tiny == a 用于任何 a ,因此定义了 exp(-1/a)。)

【问题讨论】:

至于你的问题,你的问题是什么?为什么你会想用零做除法?不要做坏事,你也不应该为这些事情担心。 @Someprogrammerdude 我不想想要用零进行除法,但我需要一个可以非常小的值的负逆指数。从数学上讲,它总是&gt;0,但我不能保证它的数值不会完全为零。所以我想知道我是否需要明确地捕捉这种情况,如果 IEEE 已经保证零情况被处理好像它是有限的。 "/运算符的结果是第一个操作数除以第二个操作数的商;% 运算符的结果是余数。在这两个操作中,if第二个操作数的值为零,行为未定义。" -- C11/6.5.5p5... 您可能应该编写一个不调用未定义行为的示例。 @Sebivor 你说的是整数除法运算符。 @leftaroundabout 引用请... 【参考方案1】:

不,依赖这个是不谨慎的。正如您链接到的 *** 问题中所述,如果您以任何方式依赖于正确处理无穷大,并且您仍想使用 -ffast-math,您还应该使用 -fno-finite-math-only 标志。

【讨论】:

以上是关于即使使用 -ffast-math 优化,exp(-1/0.) == 0 也一定能成立吗?的主要内容,如果未能解决你的问题,请参考以下文章

Exp7 网络欺诈防范

20154324 刘康权 Exp3 免杀原理与实践

logistic / sigmoid函数实现数值精度

logistic回归原理

logistic回归原理

Oracle逻辑备份恢复之exp/imp_超越OCP精通Oracle视频课程培训22