Algorithm st12次迭代:99.9998%的时间。。。除此之外
更重要的是,该算法可以更有效地处理三次方(及其倍数)的中、大功率:在最坏的情况下,简单算法将消耗超过100个CPU周期,因为它将循环20次(64位为41次)。我在这里介绍的算法不会超过25个周期 扩展到64位 将上述算法扩展到64位很简单——只需再添加一个步骤。以下是上述算法的64位版本,针对没有高效64位除法的处理器进行了优化:Algorithm st12次迭代:99.9998%的时间。。。除此之外,algorithm,math,Algorithm,Math,更重要的是,该算法可以更有效地处理三次方(及其倍数)的中、大功率:在最坏的情况下,简单算法将消耗超过100个CPU周期,因为它将循环20次(64位为41次)。我在这里介绍的算法不会超过25个周期 扩展到64位 将上述算法扩展到64位很简单——只需再添加一个步骤。以下是上述算法的64位版本,针对没有高效64位除法的处理器进行了优化: bool IsPowerOfThree(ulong nL) { // General algorithm only ulong rL; nL = Math
bool IsPowerOfThree(ulong nL)
{
// General algorithm only
ulong rL;
nL = Math.DivRem(nL, 3486784401, out rL); if(nL!=0 && rL!=0) return false;
nL = Math.DivRem(nL+rL, 59049, out rL); if(nL!=0 && rL!=0) return false;
uint n = (uint)nL + (uint)rL;
n = Math.DivRem(n, 243, out r); if(n!=0 && r!=0) return false;
n = Math.DivRem(n+r, 27, out r); if(n!=0 && r!=0) return false;
n += r;
return n==1 || n==3 || n==9;
}
for (int i=0, pow=1; i<=19, pow*=3; ++i) {
if (pow >= n) {
return pow == n;
}
}
return false;
新常数是3^20。在方法的顶部省略了优化行,因为在我们假设64位除法很慢的情况下,它们实际上会减慢速度
为什么这项技术有效
假设我想知道“1000000000000000”是否是10的幂。我可能会遵循以下步骤:
注意:在整个解释过程中,您可能一直在以十为基数思考,但如果您以三为基数思考,则可以以相同的方式阅读和理解上述整个解释,除非指数的表达方式不同(而不是“10”、“5”、“3”和“2”,我必须说“101”、“12”、“10”和“2”).简单且恒定的时间解决方案:
private bool IsPow3(int n)
{
if (n == 0) return false;
while (n % 9 == 0)
{
n /= 9;
}
return (n == 1 || n == 3);
}
return n == power(3, round(log(n) / log(3)))
二的幂之间最多有三的一次幂。 因此,下面是一个快速测试:
1
位的位置,找到n
的二进制对数。这是非常快的,因为现代处理器有专门的指令。(否则,您可以通过稍微旋转来完成,请参见)n
进行比较(如果没有三的幂,则可以使用不同的二进制对数存储任何数字)运行时主要取决于访问表项所需的时间。如果我们使用的是机器整数,那么表很小,可能在缓存中(我们使用它数百万次,否则这种优化级别就没有意义了)。下面是C中的一个漂亮而快速的实现:
bool是3的幂(无符号x){
如果(x>0x0000ffff)
x*=0xb0cd1d99;//59049的乘法逆
如果(x>0x000000ff)
x*=0xd2b3183b;//243的乘法逆
返回x对于大小有限的整数(例如32位整数),存在一种恒定时间(相当快)方法
请注意,对于整数N
为3的幂,以下为真:
对于任何MPython解决方案
from math import floor
from math import log
def IsPowerOf3(number):
p = int(floor(log(number) / log(3)))
power_floor = pow(3, p)
power_ceil = power_floor * 3
if power_floor == number or power_ceil == number:
return True
return False
这比简单的除以3的解决方案快得多
证明:3^p=数字
p log(3)=log(编号)(双侧取log)
p=log(number)/log(3)这里有一个通用算法,用于确定一个数字是否是另一个数字的幂:
bool IsPowerOf(int n,int b)
{
if (n > 1)
{
while (n % b == 0)
{
n /= b;
}
}
return n == 1;
}
另一种方法是在编译时生成一个表,好的是,你可以将它扩展到4,5,6,7的幂,不管什么
template<std::size_t... Is>
struct seq
{ };
template<std::size_t N, std::size_t... Is>
struct gen_seq : gen_seq<N-1, N-1, Is...>
{ };
template<std::size_t... Is>
struct gen_seq<0, Is...> : seq<Is...>
{ };
template<std::size_t N>
struct PowersOfThreeTable
{
std::size_t indexes[N];
std::size_t values[N];
static constexpr std::size_t size = N;
};
template<typename LambdaType, std::size_t... Is>
constexpr PowersOfThreeTable<sizeof...(Is)>
generatePowersOfThreeTable(seq<Is...>, LambdaType evalFunc)
{
return { {Is...}, {evalFunc(Is)...} };
}
template<std::size_t N, typename LambdaType>
constexpr PowersOfThreeTable<N> generatePowersOfThreeTable(LambdaType evalFunc)
{
return generatePowersOfThreeTable(gen_seq<N>(), evalFunc);
}
template<std::size_t Base, std::size_t Exp>
struct Pow
{
static constexpr std::size_t val = Base * Pow<Base, Exp-1ULL>::val;
};
template<std::size_t Base>
struct Pow<Base, 0ULL>
{
static constexpr std::size_t val = 1ULL;
};
template<std::size_t Base>
struct Pow<Base, 1ULL>
{
static constexpr std::size_t val = Base;
};
constexpr std::size_t tableFiller(std::size_t val)
{
return Pow<3ULL, val>::val;
}
bool isPowerOfThree(std::size_t N)
{
static constexpr unsigned tableSize = 41; //choosen by fair dice roll
static constexpr PowersOfThreeTable<tableSize> table =
generatePowersOfThreeTable<tableSize>(tableFiller);
for(auto a : table.values)
if(a == N)
return true;
return false;
}
模板
结构顺序
{ };
模板
结构生成顺序:生成顺序
{ };
模板
结构生成顺序:顺序
{ };
模板
可伸缩结构
{
标准:大小索引[N];
标准::大小_t值[N];
静态constexpr std::size\u t size=N;
};
模板
可伸缩的常数表达式
发电机功率三重表(序号,lambdatatype evalFunc)
{
返回{Is…},{evalFunc(Is)…};
}
模板
可控发电功率三表的恒速功率(LambdaType evalFunc)
{
返回GeneratePowerSoftThreeTable(gen_seq(),evalFunc);
}
模板
结构功率
{
静态constexpr std::size\u t val=Base*Pow::val;
};
模板
结构功率
{
静态constexpr std::size\u t val=1ULL;
};
模板
结构功率
{
静态constexpr std::size\u t val=Base;
};
constexpr std::size\u t tableFiller(std::size\u t val)
{
返回功率:val;
}
bool isPowerOfThree(标准:尺寸)
{
static constexpr unsigned tableSize=41;//通过公平掷骰选择
静态constexpr powersoftreetable=
发电机功率三表(表填料);
用于(自动a:表值)
如果(a==N)
返回true;
返回false;
}
#包括
#包括
#包括
使用名称空间std;
int main()
{
int n,幂=0;
cout这是一个常数时间方法!是的。O(1)。对于固定长度的数字,比如32位
考虑到我们需要检查一个整数n
是否是3的幂,让我们从手头已有的信息开始思考这个问题
1162261467是可装入Java int的最大3次方幂。
116261467=3^19+0
给定的n
可以表示为[(3的幂)+(一些x
)]
#!/usr/bin/python
def bits2num(bits):
num = 0
for i,b in enumerate(bits):
num += int(b) << i
return num
def num2bits(num):
base = 0
bits = list()
while True:
op = 1 << base
if op > num:
break
bits.append(op&num !=0)
base += 1
return "".join(map(str,map(int,bits)))[::-1]
def div3(bits):
n = len(bits)
if n % 2 != 0:
bits = bits + '0'
n = len(bits)
assert n % 2 == 0
q = 0
r = 0
for i in range(n/2):
pair = bits[2*i:2*i+2]
if pair == '10':
if q == 0:
q = 1
elif q == 1:
q = 2
elif q == 2:
q = 0
elif pair == '01':
if r == 0:
r = 1
elif r == 1:
r = 2
elif r == 2:
r = 0
else:
pass
return q == r
for i in range(10000):
truth = (i % 3) == 0
bits = num2bits(i)
check = div3(bits)
assert truth == check
bool IsPowerOfThree(uint n)
{
// Optimizing lines to handle the most common cases extremely quickly
if(n%3 != 0) return n==1;
if(n%9 != 0) return n==3;
// General algorithm - works for any uint
uint r;
n = Math.DivRem(n, 59049, out r); if(n!=0 && r!=0) return false;
n = Math.DivRem(n+r, 243, out r); if(n!=0 && r!=0) return false;
n = Math.DivRem(n+r, 27, out r); if(n!=0 && r!=0) return false;
n += r;
return n==1 || n==3 || n==9;
}
bool IsPowerOfThree(ulong nL)
{
// General algorithm only
ulong rL;
nL = Math.DivRem(nL, 3486784401, out rL); if(nL!=0 && rL!=0) return false;
nL = Math.DivRem(nL+rL, 59049, out rL); if(nL!=0 && rL!=0) return false;
uint n = (uint)nL + (uint)rL;
n = Math.DivRem(n, 243, out r); if(n!=0 && r!=0) return false;
n = Math.DivRem(n+r, 27, out r); if(n!=0 && r!=0) return false;
n += r;
return n==1 || n==3 || n==9;
}
return n == power(3, round(log(n) / log(3)))
bool is_power_of_3(unsigned x) {
if (x > 0x0000ffff)
x *= 0xb0cd1d99; // multiplicative inverse of 59049
if (x > 0x000000ff)
x *= 0xd2b3183b; // multiplicative inverse of 243
return x <= 243 && ((x * 0x71c5) & 0x5145) == 0x5145;
}
bool isPower3(std::uint32_t value) {
return value != 0 && 3486784401u % value == 0;
}
bool isPower3(std::int32_t value) {
return value > 0 && 1162261467 % value == 0;
}
from math import floor
from math import log
def IsPowerOf3(number):
p = int(floor(log(number) / log(3)))
power_floor = pow(3, p)
power_ceil = power_floor * 3
if power_floor == number or power_ceil == number:
return True
return False
bool IsPowerOf(int n,int b)
{
if (n > 1)
{
while (n % b == 0)
{
n /= b;
}
}
return n == 1;
}
template<std::size_t... Is>
struct seq
{ };
template<std::size_t N, std::size_t... Is>
struct gen_seq : gen_seq<N-1, N-1, Is...>
{ };
template<std::size_t... Is>
struct gen_seq<0, Is...> : seq<Is...>
{ };
template<std::size_t N>
struct PowersOfThreeTable
{
std::size_t indexes[N];
std::size_t values[N];
static constexpr std::size_t size = N;
};
template<typename LambdaType, std::size_t... Is>
constexpr PowersOfThreeTable<sizeof...(Is)>
generatePowersOfThreeTable(seq<Is...>, LambdaType evalFunc)
{
return { {Is...}, {evalFunc(Is)...} };
}
template<std::size_t N, typename LambdaType>
constexpr PowersOfThreeTable<N> generatePowersOfThreeTable(LambdaType evalFunc)
{
return generatePowersOfThreeTable(gen_seq<N>(), evalFunc);
}
template<std::size_t Base, std::size_t Exp>
struct Pow
{
static constexpr std::size_t val = Base * Pow<Base, Exp-1ULL>::val;
};
template<std::size_t Base>
struct Pow<Base, 0ULL>
{
static constexpr std::size_t val = 1ULL;
};
template<std::size_t Base>
struct Pow<Base, 1ULL>
{
static constexpr std::size_t val = Base;
};
constexpr std::size_t tableFiller(std::size_t val)
{
return Pow<3ULL, val>::val;
}
bool isPowerOfThree(std::size_t N)
{
static constexpr unsigned tableSize = 41; //choosen by fair dice roll
static constexpr PowersOfThreeTable<tableSize> table =
generatePowersOfThreeTable<tableSize>(tableFiller);
for(auto a : table.values)
if(a == N)
return true;
return false;
}
#include<iostream>
#include<string>
#include<cmath>
using namespace std;
int main()
{
int n, power=0;
cout<<"enter a number"<<endl;
cin>>n;
if (n>0){
for(int i=0; i<=n; i++)
{
int r=n%3;
n=n/3;
if (r==0){
power++;
}
else{
cout<<"not exactly power of 3";
return 0;
}
}
}
cout<<"the power is "<<power<<endl;
}
for (int i=0, pow=1; i<=19, pow*=3; ++i) {
if (pow >= n) {
return pow == n;
}
}
return false;
int pow = 1;
int next = pow * 6561; // 3**8
if (n >= next) pow = next;
next = pow * 81; // 3**4
if (n >= next) pow = next;
next = pow * 81; // 3**4; REPEATED
if (n >= next) pow = next;
next = pow * 9; // 3**2
if (n >= next) pow = next;
next = pow * 3; // 3**1
if (n >= next) pow = next;
return pow == next;
def hash(x):
return (x ^ (x>>1) ^ (x>>2)) & 31;
// Create a table and fill it with some power of three.
table = [1 for i in range(32)]
// Fill the buckets.
for n in range(20): table[hash(3**n)] = 3**n;
table = [
1162261467, 1, 3, 729, 14348907, 1, 1, 1,
1, 1, 19683, 1, 2187, 81, 1594323, 9,
27, 43046721, 129140163, 1, 1, 531441, 243, 59049,
177147, 6561, 1, 4782969, 1, 1, 1, 387420489]
def isPowerOfThree(x):
return table[hash(x)] == x
public boolean isPowerOfThree(int n) {
if (n < 1) {
return false;
}
while (n % 3 == 0) {
n /= 3;
}
return n == 1;
}
public boolean isPowerOfThree(int n) {
return Integer.toString(n, 3).matches("^10*$");
}
public boolean isPowerOfThree(int n) {
return (Math.log(n) / Math.log(3) + epsilon) % 1 <= 2 * epsilon;
}
public boolean isPowerOfThree(int n) {
return n > 0 && 1162261467 % n == 0;
}
template<int N>
struct isPowerOf3 {
static const bool cValue = (N % 3 == 0) && isPowerOf3<N / 3>::cValue;
};
template<>
struct isPowerOf3<0> {
static const bool cValue = false;
};
template<>
struct isPowerOf3<1> {
static const bool cValue = true;
};
int main() {
cout<<isPowerOf3<1162261467>::cValue;
return 0;
}
using System;
class Program
{
static void Main()
{
var sw = System.Diagnostics.Stopwatch.StartNew();
for (uint n = ~0u; n > 0; n--) ;
Console.WriteLine(sw.Elapsed); // nada 1.1 s
sw.Restart();
for (uint n = ~0u; n > 0; n--) isPow3a(n);
Console.WriteLine(sw.Elapsed); // 3^20 17.3 s
sw.Restart();
for (uint n = ~0u; n > 0; n--) isPow3b(n);
Console.WriteLine(sw.Elapsed); // % / 10.6 s
Console.Read();
}
static bool isPow3a(uint n) // Elric
{
return n > 0 && 3486784401 % n == 0;
}
static bool isPow3b(uint n) // starblue
{
if (n > 0) while (n % 3 == 0) n /= 3;
return n == 1;
}
}
using System;
class Program
{
static void Main()
{
Random rand = new Random(0); uint[] r = new uint[512];
for (int i = 0; i < 512; i++)
r[i] = (uint)(rand.Next(1 << 30)) << 2 | (uint)(rand.Next(4));
var sw = System.Diagnostics.Stopwatch.StartNew();
for (int i = 1 << 23; i > 0; i--)
for (int j = 0; j < 512; j++) ;
Console.WriteLine(sw.Elapsed); // 0.3 s
sw.Restart();
for (int i = 1 << 23; i > 0; i--)
for (int j = 0; j < 512; j++) isPow3c(r[j]);
Console.WriteLine(sw.Elapsed); // 10.6 s
sw.Restart();
for (int i = 1 << 23; i > 0; i--)
for (int j = 0; j < 512; j++) isPow3b(r[j]);
Console.WriteLine(sw.Elapsed); // 9.0 s
Console.Read();
}
static bool isPow3c(uint n)
{ return (n & 1) > 0 && 3486784401 % n == 0; }
static bool isPow3b(uint n)
{ if (n > 0) while (n % 3 == 0) n /= 3; return n == 1; }
}
def power(Num1):
while Num1 % 3 == 0:
Num1 /= 3
return Num1 == 1
Num1 = int(input("Enter a Number: "))
print(power(Num1))
return n > 0 and 1162261467 % n == 0
lg = round(log(n,3))
return 3**lg == n