确定可以分解为素数 {2,3,5,7} 的下一个最高数

Determining the next highest number that can be factored into prime numbers {2,3,5,7}

本文关键字:高数 下一个 分解      更新时间:2023-10-16

我想写一个函数,它被赋予一个无符号整数作为输入参数,并返回可以分解为素数{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(链接)等算法能够以高效方式运行。 给定的链接讨论了该算法对于长度可以分解为小素数的输入是最佳的。

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

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

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

为此,找到最高有效位并将其乘以 2。

查找最有效位的明显方法:

          未签名的 int v;用于查找日志基数 2 的 32 位字     无符号整数 r = 0;r 将是最有效位    而 (v>>= 1)      {         r++;    } 
    

基于前面的答案,如果数组将非常大~2^10,并且您希望在保持简单的同时尽可能少地使用额外的空间,您也可以选择小于x的最大幂7乘以最大幂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^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