确定可以计入素数的下一个最高数字{2,3,5,7}

时间:2012-11-25 23:00:06

标签: c++ modulus

我想写一个函数,给出一个无符号整数作为输入参数,并返回可以计入素数{2,3,5,7}的下一个最高数字。这是一段简短的代码片段,展示了我想要做的事情。

unsigned int getHigherNumber(unsigned int x)
{
    // obtain the next highest number that can be factored into
    // prime numbers (2, 3, 5, and 7)
    if (~(x % 2 || x % 3 || x % 5 || x % 7))
        return  x;
    else
    {
         // ???
    }  
} // end

此函数的目的是找到应填充数组的零的数量,以确保FFTW(link)等算法能够以有效的方式运行。给定的链接讨论了该算法对于可以被分解为小素数的长度的输入是最优的。

正如对这个问题的评论所建议的那样,如果FFTW算法是最优的,那么似乎只允许使用2 ^ a * 3 ^ b * 5 ^ c * 7 ^ d形式的数字。

3 个答案:

答案 0 :(得分:5)

例如,标准FFTW分布对于大小可以被分解为小素数(2,3,5和7)的数组效率最高,否则它使用较慢的通用常规。

真的,你不需要下一个最高,但只是相当接近的东西。最简单的方法就是选择最接近的2的幂。这最多会浪费原始阵列的大小。

要执行此操作,请找到最高位并将其乘以2.

The obvious way of finding the most significant bit:


    unsigned int v; // 32-bit word to find the log base 2 of  
    unsigned int r = 0; // r will be most significant bit

    while (v >>= 1)   
    {  
        r++;
    }  

答案 1 :(得分:2)

基于之前的答案,如果数组将会非常大~2 ^ 10,并且您希望尽可能少地使用额外空间,同时保持简单,您还可以选择7的最小功率x,乘以5的最大幂,依此类推。那是

unsigned int getHigherNumber(unsigned int x)
{
    unsigned int ans=1;
    unsigned int primes[4]={2,3,5,7};
    for(int i=3; i>=0; i--)
    {
        for(int j=0; ; j++)
        {
            if(pow(primes[i],j)>x)
            {
                ans*=pow(7,j-1);
                if(i==0)
                    ans*=2;
                break;
            }
        }
    }
    return ans;
}

(未测试)。我认为应该以一些速度为代价来获得比最接近2的幂更小的数字。但它绝对不是最佳选择。

答案 2 :(得分:0)

以下算法和源代码可能无法高度优化,无法找到下一个最高数量的通用形式(2 ^ a * 3 ^ b * 5 ^ c * 7 ^ d),但它的代码很有用将返回具有这些权力之一的最高数字。

该算法首先检查该数字是否是{2,3,5,7}的幂。如果是,则返回该号码。如果不是,则算法找到高于输入数的最小功率。

更复杂的方法会使用素数因子分解 算法和搜索/排序,或者可能是硬编码的查找表, 但是这些解决方案对于这种应用来说可能过于复杂。

#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>

// http://stackoverflow.com/questions/1804311/how-to-check-if-an-integer-is-power-of-3
// Checks if n^x
int powerOf(int n, int x)
{
    while (n % x == 0) 
    {
        n /= x;
    }
return n == 1;
}

unsigned int hN(unsigned int x, unsigned int base)
{
    double exponent = std::ceil( std::log(x) / std::log(base) );
    double num = std::pow(base, exponent);
return static_cast<unsigned int>(num);
}

unsigned int getHigherNumber(unsigned int n)
{
    unsigned int rv = n;
    const int pnum = 4;

    // 1) Is the number a power of {2,3,5,7}?
    // If it is, then simply return it
    if(powerOf(n,2)) return rv;
    if(powerOf(n,3)) return rv;
    if(powerOf(n,5)) return rv;
    if(powerOf(n,7)) return rv;

    // 2) If not, then find next highest power of {2,3,5,7} that is the smallest
    // number higher than n
    unsigned int num0 = hN(n, 2);
    unsigned int num1 = hN(n, 3);
    unsigned int num2 = hN(n, 5);
    unsigned int num3 = hN(n, 7);

    std::vector<unsigned int>v(pnum);
    v[0] = num0;
    v[1] = num1;
    v[2] = num2;
    v[3] = num3;
    rv = *std::min_element(v.begin(),v.end());

    // 3) TODO: More sophisticated methods would use prime-factorization
    // algorithms and searching/sorting, or perhaps a look-up table, 
    // but these may be too complex for this application

 return rv;
} // end


int main()
{
    // const unsigned int num = 64;
    // const unsigned int num = 18;
    const unsigned int num = 2234;
    std::cout << "num = " << num << std::endl;
    std::cout << "higher number = " << getHigherNumber( num ) << std::endl;

} // end