我使用compile-time int powers计算Power,来计算n ** p。它使用整数。 我想计算比int大的东西,好吗? 它适合u64(unsigned long long)。 C ++模板可以在u64上进行编译时计算吗?枚举不能这样做。 在双打?可能?
我真的希望该类型是模板的arg。可能吗 ? 我的编译器不是c ++ 0x。
由于 安德烈
template<int N, int P> struct Power {
enum { val = N * Power<N, P-1>::val };
};
template<int N> struct Power<N, 0> {
enum { val = 1 };
};
int result = Power<2, 5>; // 2**5 == 32
答案 0 :(得分:3)
是的,您可以对任何基本整数类型进行编译时计算。但是,您不能对浮点值进行计算,因为模板不能对这些值进行参数化。即将推出的C ++ 0x标准将引入特殊类来进行编译时合理算术,因此如果您愿意,也可以使用它。
答案 1 :(得分:2)
template<int N, unsigned int P> struct Power {
static const unsigned long long val = N * Power<N, P-1>::val;
};
template<int N> struct Power<N, 0> {
static const unsigned long long val = 1;
}
请注意,我将P
设为unsigned int
,因为您的模板会因为负值而失败。
答案 2 :(得分:2)
为了扩展sbi的实现,这里是一个逐个取幂的方法(需要更少的大型模板实例化)。
请注意,如果你真的只想计算2的幂,你只需要左移(即2**x == 1 << x
),而不是做所有这些模板的东西。
#include <iostream>
template <unsigned long long N, unsigned int P, int Odd = (P&1)> struct Power;
template <unsigned long long N, unsigned int P>
struct Power<N,P,0> { // even (square N and halve the power)
static const unsigned long long val = Power<N*N,(P/2)>::val;
};
template <unsigned long long N, unsigned int P>
struct Power<N,P,1> { // odd (multiply by N and decrement the power)
static const unsigned long long val = N * Power<N,(P-1)>::val;
};
template <unsigned long long N>
struct Power<N,0,0> { // zero (x**0 is 1 for all x != 0)
static const unsigned long long val = 1;
};
int main() {
std::cout << "2**0 = " << Power<2,0>::val << "\n";
std::cout << "2**1 = " << Power<2,1>::val << "\n";
std::cout << "2**2 = " << Power<2,2>::val << "\n";
std::cout << "2**3 = " << Power<2,3>::val << "\n";
std::cout << "2**4 = " << Power<2,4>::val << "\n";
std::cout << "2**5 = " << Power<2,5>::val << "\n";
std::cout << "2**6 = " << Power<2,6>::val << "\n";
std::cout << "2**7 = " << Power<2,7>::val << "\n";
std::cout << "2**8 = " << Power<2,8>::val << "\n";
std::cout << "2**9 = " << Power<2,9>::val << "\n";
std::cout << "2**10 = " << Power<2,10>::val << "\n";
std::cout << "2**11 = " << Power<2,11>::val << "\n";
std::cout << "2**12 = " << Power<2,12>::val << "\n";
std::cout << "2**30 = " << Power<2,30>::val << "\n";
std::cout << "2**40 = " << Power<2,40>::val << "\n";
std::cout << "2**50 = " << Power<2,50>::val << "\n";
std::cout << "2**60 = " << Power<2,60>::val << "\n";
return 0;
}
免责声明:由于模板实例化数量减少(尽管可能),我没有声称此代码必须更快地编译。我真的只把它写成玩具演示。我将其作为练习让读者编写一个版本,该版本在使用Odd
时不会明显传递Power<>
参数的值。
答案 3 :(得分:2)
你可以使用多精度数学来计算大数(在我的例子中,我使用带有3个模板参数的96位计算,你可以使用任何常数)。您需要有多个整数作为模板参数。
执行编译时乘法时,您应该将具有64位结果的32位数相乘;结果应该分成2个模板参数。
溢出检查可能是可能的,但可能很棘手。
const uint64_t W = 1000000000; // word size: 2^32 is best; any smaller number is OK
// I use a power of 10 as word size for ease of printing (see main() below)
// The following class performs multiplication of (n0 + W*n1 + W*W*n2) by (base)
template <unsigned n0, unsigned n1, unsigned n2, uint64_t base, unsigned p> class power_temp
{
typedef power_temp<
n0 * base % W,
n1 * base % W + n0 * base / W,
n2 * base % W + n1 * base / W,
base, p - 1> mult_type;
public:
static const unsigned x0 = mult_type::x0;
static const unsigned x1 = mult_type::x1;
static const unsigned x2 = mult_type::x2;
};
// The following partial specialization is used to end recursion
template <unsigned n0, unsigned n1, unsigned n2, uint64_t base>
class power_temp<n0, n1, n2, base, 0>
{
public:
static const unsigned x0 = n0;
static const unsigned x1 = n1;
static const unsigned x2 = n2;
};
// The following class calculates a power, using compile-time calculations
template <unsigned base, unsigned p> struct power
{
static const unsigned x0 = power_temp<1, 0, 0, base, p>::x0;
static const unsigned x1 = power_temp<1, 0, 0, base, p>::x1;
static const unsigned x2 = power_temp<1, 0, 0, base, p>::x2;
};
int main()
{
typedef power<123456789, 3> my1;
printf("%09d%09d%09d\n", my1::x2, my1::x1, my1::x0);
typedef power<5, 33> my2;
printf("%09d%09d%09d\n", my2::x2, my2::x1, my2::x0);
}