Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm st12次迭代:99.9998%的时间。。。除此之外_Algorithm_Math - Fatal编程技术网

Algorithm st12次迭代:99.9998%的时间。。。除此之外

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

更重要的是,该算法可以更有效地处理三次方(及其倍数)的中、大功率:在最坏的情况下,简单算法将消耗超过100个CPU周期,因为它将循环20次(64位为41次)。我在这里介绍的算法不会超过25个周期

扩展到64位

将上述算法扩展到64位很简单——只需再添加一个步骤。以下是上述算法的64位版本,针对没有高效64位除法的处理器进行了优化:

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^10,得到一个10000000的商和一个0的余数。这些数字增加到10000000
  • 我除以10^5,得到100的商和0的余数。这些加起来是100
  • 我除以10^3,得到的商是0,余数是100。这些加起来是100
  • 我除以10^2,得到1的商和0的余数。这些加起来是1
  • 因为我从10的幂开始,每次除以10的幂,我就得到一个零商或零余数。如果我开始的时候没有10的幂,我迟早会得到一个非零商或余数

    在本例中,我选择了10、5和3的指数来匹配前面提供的代码,并添加了2以进行检查。其他指数也可以工作:有一个简单的算法,可以根据您的最大输入值和输出中允许的最大功率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