【发布时间】:2021-11-12 10:41:47
【问题描述】:
我想快速计算 10(是的,只有 10)的 n[0..308] 次幂。我想出了一些方法。
1)
double f(int n) {
return pow(10.0, n);
}
double f1(int n) {
double a = 10.0;
double res = 1.0;
while(n) {
if(n&1) res *= a;
a *= a;
n >>= 1;
}
return res;
}
时间:O(logn),可以更快吗? ( // f1() 可以做一点优化,但仍然是 O(logn))
2)
double f2(int n) {
static const double e[] = { 1e+0, 1e+1, 1e+2, ..., 1e+308 };
return e[n];
}
时间:O(1),非常好。 但是空间:309 * 8 字节 = 2472 字节……哎呀,它太大了……
3)
double f3(int n){
static const double e[] = {
1e+1, 1e+2, 1e+4, 1e+8, 1e+16, 1e+32, 1e+64, 1e+128, 1e+256
};
double res = 1.0;
for(int i = 0; n; ++i){
if(n & 1){
res *= e[i];
}
n >>= 1;
}
return res;
}
f3 结合 f1 和 f2 以避免乘法,例如 1e128*1e128,我希望它更快,但是.. 实际上 f3 比 f2 慢.. 因为 ++i 我猜..
好吧,在我输入这些代码之前我几乎放弃了,
int main(){
double d = 1e+2;
return 0;
}
并通过g++编译成.s
LCPI0_0:
.quad 0x4059000000000000 ## double 100
编译器如何知道 1e+2 是 0x4059000000000000?
我的意思是我想要得到的只是一个双值 1e+n。但是当编译器编译“double d = 1e+2”时,它知道 d 应该是 0x4059000000000000。我可以使用某种方法直接返回 1e+n 之类的东西吗?或者我可以做一些 C/C++ 之外的事情来获得我的价值吗?
非常感谢。如有错误或不清楚的地方请指出。
【问题讨论】:
-
您的问题是编译器如何知道如何存储
1e+2?也许this 会对此有所了解。 -
1e+2是一个双 literal - 如果编译器无法将文字翻译成其 IEEE 754 表示(或任何可能的表示),它怎么能完成它的工作?在混凝土机器上使用,IEEE 754 不是强制性的......)。 -
如果这对性能至关重要并且没有嵌入到一些微小的硬件上,那么 f2 中的表格似乎并不大。请注意,您还可以有一个较小的表,例如最多 32 个,将 n 拆分为 a+b
-
你经常这样做吗?如果是,那么 SIMD 将是更好的解决方案
标签: c++ compiler-construction double pow