10的幂的表查找
Table lookups of Powers of 10
我正在进行一个C++项目,在该项目中计算速度至关重要。任何我能剪的时候,都应该剪。可执行文件的最终大小和内存使用情况并不重要。
话虽如此,创建一个预先计算的10次方查找表是否有益?例如,如果我有一个简化的函数:
double powTen(int exponent) {
return pow(10, exponent);
}
如果我用表查找取代pow()
,它的性能会有(小)提高吗?这值得吗?似乎pow()
函数一定相当复杂。此外,GCC对此有特殊的优化吗?
表查找对于性能来说几乎总是很好的。因此,假设您已经确定这是一个瓶颈,我会将时间用于实现生成表的模板。但是,一定要测量。性能在现代计算机上是一种奇怪的野兽。它可以朝着人们永远不会相信的方向发展。
我预计实现编译时间表生成的时间确实很短。但事实证明,Visual C++2015,至少在旧的更新2中,对类中的constexpr std::array
一点也不满意。然而,在最后,一个原始数组起了作用。
代码,使用MinGW g++6.3.0和Visual C++2015更新2:编译
#include <stddef.h> // size_t, ptrdiff_t
#include <utility> // std::(make_index_sequence, )
namespace my {
using std::make_index_sequence;
using std::index_sequence;
using Size = ptrdiff_t;
template< Size n, class Item >
using raw_array_of_ = Item[n];
template< class Item, size_t n >
constexpr
auto n_items_of( raw_array_of_<n, Item>& )
-> Size
{ return n; }
namespace impl {
constexpr
auto compile_time_pow_of_10( int const n )
-> double
{ return (n == 0? 1.0 : 10.0*compile_time_pow_of_10( n - 1 )); }
template< size_t... indices >
struct Powers_of_10_
{
static constexpr size_t n = sizeof...(indices);
static constexpr raw_array_of_<n, double> table =
{
compile_time_pow_of_10( indices )...
};
constexpr
Powers_of_10_() {}
};
template< size_t... indices >
constexpr
raw_array_of_<Powers_of_10_<indices...>::n, double>
Powers_of_10_<indices...>::table;
template< size_t... indices, int n = sizeof...(indices) >
constexpr
auto power_of_10_table_helper( index_sequence<indices...> )
-> const raw_array_of_<n, double>&
{ return Powers_of_10_<indices...>::table; }
} // namespace impl
template< int n >
constexpr
auto power_of_10_table()
-> const raw_array_of_<n, double>&
{ return impl::power_of_10_table_helper( make_index_sequence<n>() ); }
} // namespace my
#include <iostream>
using namespace std;
auto main()
-> int
{
int const n = 7;
constexpr auto& pow_10 = my::power_of_10_table<n>();
cout << n << " powers of 10:n";
cout << fixed; cout.precision( 0 );
for( int i = 0; i < n; ++i )
{
cout << pow_10[i] << "n";
}
}
模板代码可能很难移植。也就是说:Visual C++2015拒绝接受上述代码中的std::array
,因此需要重写以使用原始数组。它也很难维护,因为通常编译诊断程序过长且晦涩难懂。
合理快速的积分幂函数可以通过将幂表示为形式为x(2n)的幂的乘积来定义。例如,x42=x32‧x8∙x2,并且x-的这些更基本的幂,即2、8和32,可以通过反复对x-求平方来计算。这将乘法运算的次数从指数中的线性减少到指数中的对数。
代码:
#include <stddef.h> // size_t, ptrdiff_t
namespace my {
using Size = ptrdiff_t;
template< Size n, class Item >
using raw_array_of_ = Item[n];
namespace impl {
auto positive_integral_power_of( const double x, const int n )
{
double result = 1.0;
double power = x;
for( unsigned exp = n; ; )
{
if( (exp & 1) != 0 )
{
result *= power;
}
exp >>= 1;
if( exp == 0 )
{
break;
}
power *= power;
}
return result;
}
} // namespace impl
auto integral_power_of( const double x, const int n )
-> double
{
return
n > 0?
impl::positive_integral_power_of( x, n ) :
n < 0?
1.0 / impl::positive_integral_power_of( x, -n ) :
1.0;
}
} // namespace my
#include <iostream>
using namespace std;
auto main()
-> int
{
int const n = 7;
cout << n << " powers of 10:n";
cout << fixed; cout.precision( 0 );
for( int i = 0; i < n; ++i )
{
cout << my::integral_power_of( 10, i ) << "n";
}
}
您可以通过使用循环来提高函数的效率:
double powerTen(int exponent)
{
double result = 1.0;
for (int i = 0; i < exponent; ++i)
{
result = result * 10.0;
}
return result;
}
循环的一个好处是可以消除pow
函数的函数调用开销。节省不了多少钱,IMO.
另一种选择是表格查找:
double powerTen(int exponent)
{
static const double values[] = {1.0, 10.0, 100.0, 1000.0};
return values[exponent];
}
您正在用内存空间换取执行时间
此外,您可能希望添加一些数组溢出检查以及处理负指数。
你调用这个函数那么多吗?如果是这样,那么预计算期望值会更好。
您也可以使用部分构建的表,并根据使用情况进行构建,即第一次调用10^5时计算它,然后保存在表中,以便下次从表中获取它。
使用表总是比调用函数好,但问题是它必须首先值得,通过多次调用或多次发送相同的参数,这样你就不会在第一个大时间调用函数,然后根本不使用,这会破坏你优化的初衷。
- 正在查找文档以获得PS4平台的C++中的设备信息
- 在C++中查找文件
- 模板元程序查找相似的连续类型名称
- 在UNIX系统中使用DIR查找文件的字节大小
- 查找最接近的大于当前数字的数字的索引
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 查找后更改类变量
- 使用正则表达式regex_search在字符串中查找字符串
- 使用gcc从静态链接的文件中查找可选符号
- 在C++中查找范围的长度
- 算法问题:查找从堆栈中弹出的所有序列
- 在Windows中查找扬声器输出的当前音量级别
- 如何在C++中使用X509证书模在令牌中查找私钥
- 使用.find函数在c++中查找字符和另一个字符之间的大小
- 在 Windows 上,是否可以让 dll 在不使用 PATH 环境变量的情况下在另一个文件夹中查找依赖项?
- 在 for 循环中查找问题时遇到困难
- 如何在文件中查找字节序列
- 试图创建一个多线程程序来查找0-100000000之间的总素数
- 使用堆查找第K个最大元素的时间复杂性
- 一个函数,用于查找字符串1包含字符串2 c++的次数