Ale*_*son 44 c++ math floating-point
使用此代码有什么好处
double x;
double square = pow(x,2);
Run Code Online (Sandbox Code Playgroud)
而不是这个?
double x;
double square = x*x;
Run Code Online (Sandbox Code Playgroud)
我更喜欢x*x并且查看我的实现(Microsoft)我发现pow没有优势,因为x*x比特定方形情况下的pow更简单.
有什么特别的情况,战俘优越吗?
Aln*_*tak 54
FWIW,MacOS X 10.6上的gcc-4.2和-O3编译器标志,
x = x * x;
Run Code Online (Sandbox Code Playgroud)
和
y = pow(y, 2);
Run Code Online (Sandbox Code Playgroud)
导致相同的汇编代码:
#include <cmath>
void test(double& x, double& y) {
x = x * x;
y = pow(y, 2);
}
Run Code Online (Sandbox Code Playgroud)
装配到:
pushq %rbp
movq %rsp, %rbp
movsd (%rdi), %xmm0
mulsd %xmm0, %xmm0
movsd %xmm0, (%rdi)
movsd (%rsi), %xmm0
mulsd %xmm0, %xmm0
movsd %xmm0, (%rsi)
leave
ret
Run Code Online (Sandbox Code Playgroud)
因此,只要你使用一个像样的编译器,编写对你的应用程序更有意义的,但考虑到pow(x, 2)它永远不会比简单的乘法更优化.
Seb*_*ach 24
std :: pow更具表现力,如果你的意思是x²,x x更具表现力,如果你的意思是x x,特别是如果你只是编写一篇例如科学论文,读者应该能够理解你的实现与论文.x*x /x²的区别可能很微妙,但我认为如果你通常使用命名函数,它会增加代码的可靠性和可读性.
在现代编译器上,例如g ++ 4.x,std :: pow(x,2)将被内联,如果它甚至不是编译器内置的,并且强度减少到x*x.如果不是默认情况下并且您不关心IEEE浮点类型一致性,请查看编译器手册以获得快速数学开关(g ++ == -ffast-math).
旁注:有人提到包括math.h会增加程序大小.我的回答是:
在C++中,你
#include <cmath>,不是MATH.H.此外,如果你的编译器不是很老,它只会增加你的程序大小(在一般情况下),如果你的std :: pow实现只是内联到相应的x87指令,那么现代的g ++用x*x强度降低x²,然后没有相应的尺寸增加.此外,程序大小永远不应该决定你的代码是多么富有表现力.
cmath比math.h的另一个优点是,使用cmath,你得到每个浮点类型的std :: pow重载,而使用math.h你可以在全局命名空间中得到pow,powf等,所以cmath增加了适应性代码,特别是在编写模板时.
作为一般规则:首选表达式和清晰的代码,而不是基于可疑的性能和二进制大小的合理代码.
另见Knuth:
"我们应该忘记小的效率,大约97%的时间说:过早的优化是所有邪恶的根源"
和杰克逊:
程序优化的第一条规则:不要这样做.程序优化的第二条规则(仅限专家!):不要这样做.
Dav*_*nan 13
不仅x*x更清楚,它肯定至少会如此快pow(x,2).
Dav*_*men 11
这个问题触及了大多数关于科学编程的C和C++实现的关键弱点之一.从Fortran转到C大约二十年,之后转到C++,这仍然是那些偶尔让我怀疑这种转换是否是一件好事的痛处之一.
问题简而言之:
pow是Type pow(Type x; Type y) {return exp(y*log(x));}x*x,简单的方法pow(x,2)是计算上非常昂贵并且失去精度.与针对科学编程的语言相比:
pow(x,y).这些语言具有内置的取幂运算符.C和C++坚决拒绝实现取幂运算符,这使得许多科学程序员的血液沸腾了.对于一些顽固的Fortran程序员来说,仅此一点就是永远不会切换到C的理由.依赖高优化级别来"做正确的事"是一个问题.我曾为多家禁止在安全关键软件中使用优化的组织工作过.在这里损失1000万美元,其中有1亿美元,记忆可能会很长(数十年之久),这都归功于一些优化编译器中的错误.
恕我直言,你应该从来没有使用pow(x,2)C或C++.在这个意见中,我并不孤单.pow(x,2)通常使用的程序员在代码审查期间会大量使用.
Sha*_*our 10
在C++ 11中,有一种情况是使用x * xover 有一个优点std::pow(x,2),那就是你需要在constexpr中使用它的情况:
constexpr double mySqr( double x )
{
return x * x ;
}
Run Code Online (Sandbox Code Playgroud)
我们可以看到std :: pow没有标记为constexpr,因此它在constexpr函数中无法使用.
否则从性能角度看,将以下代码放入godbolt会显示以下函数:
#include <cmath>
double mySqr( double x )
{
return x * x ;
}
double mySqr2( double x )
{
return std::pow( x, 2.0 );
}
Run Code Online (Sandbox Code Playgroud)
生成相同的汇编:
mySqr(double):
mulsd %xmm0, %xmm0 # x, D.4289
ret
mySqr2(double):
mulsd %xmm0, %xmm0 # x, D.4292
ret
Run Code Online (Sandbox Code Playgroud)
我们应该期待任何现代编译器的类似结果.
值得注意的是,目前gcc认为pow是一个constexpr,也包括在这里,但这是一个不合格的扩展,不应该依赖,并可能会在以后的版本中更改gcc.
x * x将始终编译为简单的乘法. pow(x, 2)很可能,但绝不保证,优化到相同.如果没有进行优化,则可能会使用缓慢的通用升频数学例程.因此,如果您关注性能,那么您应该始终青睐x * x.
恕我直言:
pow(x, 6),可能实现特定处理器的某些浮点机制等.干杯
| 归档时间: |
|
| 查看次数: |
53596 次 |
| 最近记录: |