即使使用 -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
结果。
但是,对于负参数,指数函数(至少在数学上)非常稳定:任何 有限 值 < -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 我不想想要用零进行除法,但我需要一个可以非常小的值的负逆指数。从数学上讲,它总是>0
,但我不能保证它的数值不会完全为零。所以我想知道我是否需要明确地捕捉这种情况,如果 IEEE 已经保证零情况被处理好像它是有限的。
"/运算符的结果是第一个操作数除以第二个操作数的商;% 运算符的结果是余数。在这两个操作中,if第二个操作数的值为零,行为未定义。" -- C11/6.5.5p5... 您可能应该编写一个不调用未定义行为的示例。
@Sebivor 你说的是整数除法运算符。
@leftaroundabout 引用请...
【参考方案1】:
不,依赖这个是不谨慎的。正如您链接到的 *** 问题中所述,如果您以任何方式依赖于正确处理无穷大,并且您仍想使用 -ffast-math
,您还应该使用 -fno-finite-math-only
标志。
【讨论】:
以上是关于即使使用 -ffast-math 优化,exp(-1/0.) == 0 也一定能成立吗?的主要内容,如果未能解决你的问题,请参考以下文章