c語言中x*x和pow(x,2)哪個計算更快一點?
x*x*...x 和 pow(x, n)呢?
https://godbolt.org/g/1PZ8GV
如果x*x更慢,那你就可以去打死你用的編譯器的實現者了。
編程三大錯覺之首:我比編譯器聰明
據評論區要求附上二三,來源來自無數年前看見的bbs我超越了標準庫我能管理好內存/* Complex power of float type.
Copyright (C) 1997-2017 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper &
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
&
#include & CFLOAT declare_mgen_alias (__cpow, cpow) #if M_LIBM_NEED_COMPAT (cpow) 上面是gcc的glibc中,math庫對pow( )函數的實現。 在數學上就是 比x*x複雜,但通用性強。 再看一下另一個系統的實現代碼: { /* Avoid internal underflow for tiny y. The exact value of y does if (isinf (retval)) if (x == 0) /* if x&<0 */
if (u.i[HIGH_HALF] &< 0)
{
k = checkint (y);
if (k == 0)
{
if (qy == 0x7ff00000)
{
if (x == -1.0)
return 1.0;
else if (x &> -1.0) if (qx == 0x7ff00000) /* x= 2^-0x3ff */ if (qy &> 0x45f00000 qy &< 0x7ff00000)
{
if (x == 1.0)
return 1.0;
if (y &> 0) 看到
#include &
M_DECL_FUNC (__cpow) (CFLOAT x, CFLOAT c)
{
return M_SUF (__cexp) (c * M_SUF (__clog) (x));
}
declare_mgen_libm_compat (__cpow, cpow)
#endif
/* An ultimate power routine. Given two IEEE double machine numbers y, x it
computes the correctly rounded (to nearest) value of X^y. */
double
SECTION
__ieee754_pow (double x, double y)
{
double z, a, aa, error, t, a1, a2, y1, y2;
mynumber u, v;
int k;
int4 qx, qy;
v.x = y;
u.x = x;
if (v.i[LOW_HALF] == 0)
{ /* of y */
qx = u.i[HIGH_HALF] 0x7fffffff;
/* Is x a NaN? */
if ((((qx == 0x7ff00000) (u.i[LOW_HALF] != 0)) || (qx &> 0x7ff00000))
(y != 0 || issignaling (x)))
return x + x;
if (y == 1.0)
return x;
if (y == 2.0)
return x * x;
if (y == -1.0)
return 1.0 / x;
if (y == 0)
return 1.0;
}
/* else */
if (((u.i[HIGH_HALF] &> 0 u.i[HIGH_HALF] &< 0x7ff00000) || /* x&>0 and not x-&>0 */
(u.i[HIGH_HALF] == 0 u.i[LOW_HALF] != 0))
/* 2^-1023&< x&<= 2^-1023 * 0x1.0000ffffffff */
(v.i[HIGH_HALF] 0x7fffffff) &< 0x4ff00000)
{ /* if y&<-1 or y&>1 */
double retval;
SET_RESTORE_ROUND (FE_TONEAREST);
not matter if |y| &<= 2**-64. */
if (fabs (y) &< 0x1p-64)
y = y &< 0 ? -0x1p-64 : 0x1p-64;
z = log1 (x, aa, error); /* x^y =e^(y log (X)) */
t = y * CN;
y1 = t - (t - y);
y2 = y - y1;
t = z * CN;
a1 = t - (t - z);
a2 = (z - a1) + aa;
a = y1 * a1;
aa = y2 * a1 + y * a2;
a1 = a + aa;
a2 = (a - a1) + aa;
error = error * fabs (y);
t = __exp1 (a1, a2, 1.9e16 * error); /* return -10 or 0 if wasn"t computed exactly */
retval = (t &> 0) ? t : power1 (x, y);
}
retval = huge * huge;
else if (retval == 0)
retval = tiny * tiny;
else
math_check_force_underflow_nonneg (retval);
return retval;
}
{
if (((v.i[HIGH_HALF] 0x7fffffff) == 0x7ff00000 v.i[LOW_HALF] != 0)
|| (v.i[HIGH_HALF] 0x7fffffff) &> 0x7ff00000) /* NaN */
return y + y;
if (fabs (y) &> 1.0e20)
return (y &> 0) ? 0 : 1.0 / 0.0;
k = checkint (y);
if (k == -1)
return y &< 0 ? 1.0 / x : x;
else
return y &< 0 ? 1.0 / 0.0 : 0.0; /* return 0 */
}
qx = u.i[HIGH_HALF] 0x7fffffff; /* no sign */
qy = v.i[HIGH_HALF] 0x7fffffff; /* no sign */
if (qx &>= 0x7ff00000 (qx &> 0x7ff00000 || u.i[LOW_HALF] != 0)) /* NaN */
return x + y;
if (qy &>= 0x7ff00000 (qy &> 0x7ff00000 || v.i[LOW_HALF] != 0)) /* NaN */
return x == 1.0 !issignaling (y) ? 1.0 : y + y;
return v.i[HIGH_HALF] &< 0 ? INF.x : 0.0;
else
return v.i[HIGH_HALF] &< 0 ? 0.0 : INF.x;
}
else if (qx == 0x7ff00000)
return y &< 0 ? 0.0 : INF.x;
return (x - x) / (x - x); /* y not integer and x&<0 */
}
else if (qx == 0x7ff00000)
{
if (k &< 0)
return y &< 0 ? nZERO.x : nINF.x;
else
return y &< 0 ? 0.0 : INF.x;
}
/* if y even or odd */
if (k == 1)
return __ieee754_pow (-x, y);
else
{
double retval;
{
SET_RESTORE_ROUND (FE_TONEAREST);
retval = -__ieee754_pow (-x, y);
}
if (isinf (retval))
retval = -huge * huge;
else if (retval == 0)
retval = -tiny * tiny;
return retval;
}
}
/* x&>0 */
return y &> 0 ? x : 0;
return (x &> 1.0) ? huge * huge : tiny * tiny;
if (y &< 0)
return (x &< 1.0) ? huge * huge : tiny * tiny;
}
if (x == 1.0)
return 1.0;
if (y &> 0)
return (x &> 1.0) ? INF.x : 0;
if (y &< 0)
return (x &< 1.0) ? INF.x : 0;
return 0; /* unreachable, to make the compiler happy */
}
if (y == 2.0)
return x * x;
了吧
裸代碼的話,pow(x,2)多一次函數調用,入棧出棧會帶來額外的性能開銷。但是開了優化之後,編譯器基本上會把這點差別給抹掉,所以你不用考慮這個。
編譯器:來來來,筆給你,你來優化。
算連乘,乘的越多越好優化。
例如,算x^10,優化演算法可以先算
x^2
然後再算x^4
然後再算x^8
最後算x^8*x^2一共幾次乘法?
4次
直接乘就是9次啦如果是整型的話,肯定是*快,其它的就看你開不開優化了。
不邀自答
一個函數再怎麼的也要return對吧!
僅針對x*x 和pow(x,2)這些基本數據類型的計算(對彙編最後都是 加,是的連除法最後也要轉成 加)如果沒有邏輯轉換的話(對彙編就是jump),彙編幾乎不可能不同的(現代彙編已經優化的幾乎到了極致)。
反對 @我是水軍 的回答
怎麼想都是x*x快啊
@我是水軍 認為 pow是定製操作 可以在特定情況下 比 x*x 更快
我很好奇怎麼定製pow能比x*x更優越
於是 他貼出來下圖
黑人問號.jpg
imul ?? 這就是定製優化
x是1.5怎麼辦 @我是水軍 認為不考慮 不存在
pow2就是定製就是快
x是int 這麼說 @我是水軍 認為不考慮 不存在
pow2就是定製就是快
GG
pow2連基本功能都沒完成 這能叫做定製
推薦閱讀:
※2==c會導致的這樣的異常嗎?
※c語言可以釋放數組中的單個元素結構么?
※怎麼用c語言實現分形圖形?
※如何通俗地解釋 C 語言中 #include<> 的用途?
TAG:C編程語言 |