【问题标题】:Improve/fix prime factorization function改进/修复素数分解功能
【发布时间】:2021-12-13 14:33:59
【问题描述】:

我有一个函数素因数分解,但它的工作很奇怪,我不知道如何使它正确。 如果 2 或 3 是重复因子,则应通过 'x' 打印因子并写成 2^(power) 或 3^(power)。

我的输出:2 >> 22^2 | 6 >> 2 x 3^2 | 8 >> 22^22^3 | 9 >> 3 x 3^2.
如何更改此代码以使其正常工作。

注意:我已经在 main() 中声明如果 num == 1:打印 1。

void prime_factors(int num)
{
    int power = 0;

    for (int factor = 2; num > 1; ++factor)
    {
        while (num % factor == 0)
        {
            if (factor >= 3 && power >= 1)
                printf(" x %d", factor);
            else
                printf("%d", factor);
            num /= factor;
            ++power;
            if (power >= 1)
            {
                printf("^%d", power);
            }
        }
    }
}

【问题讨论】:

  • 选择一个不太容易分解的小数,例如 12=2^2 x 3^2 和 60: 2^2 x 3 x 5 并尝试在您的代码后面加上纸页和一支铅笔。你应该很快意识到这是错误的,为什么......
  • 我马上就看到了一个问题:在 factor 循环的每次迭代开始时,您永远不会将 power 重置为 0。对于这样一个简单的程序,您可以轻松地尝试一个简单的失败案例并手动浏览代码以查看会发生什么。
  • 谢谢。现在我离正确答案有点近了,但还有一些事情要做

标签: c function factorization


【解决方案1】:

有四个问题:

  1. power 不会针对每个因素重置为 0
  2. 即使power 为0,也会打印factor
  3. 在完全确定power 之前,不应打印factorpower。 (目前,每次power 递增时都会打印代码。
  4. 如果第一个因子 > 2,它会在开头打印 x

以下固定版本:

void prime_factors(int num)
{
    int power = 0;
    int first = 1;

    for (int factor = 2; num > 1; ++factor)
    {
        power = 0;
        while (num % factor == 0)
        {
            num /= factor;
            ++power;
        }
        if (power >= 1)
        {
            if (first)
                printf("%d", factor);
            else
                printf(" x %d", factor);
            printf("^%d", power);
            first = 0;
        }
    }
}

有多种方法可以加快速度。

加快速度的一种方法是在因子变得太大时跳过因子(大于 num 的平方根,如 cmets 中的 @chux 所建议),留下 num作为唯一剩下的因素。可以使用简单的除法而不是计算平方根,如下面的// speed up 1 代码部分所示:

void prime_factors(int num)
{
    int power = 0;
    int first = 1;

    for (int factor = 2; num > 1; ++factor)
    {
        power = 0;
        // speed up 1
        if (num / factor < factor)
        {
            // skip impossible factors
            factor = num;
        }
        // end of speed up 1
        while (num % factor == 0)
        {
            num /= factor;
            ++power;
        }
        if (power >= 1)
        {
            if (first)
                printf("%d", factor);
            else
                printf(" x %d", factor);
            printf("^%d", power);
            first = 0;
        }
    }
}

另一种加快速度的方法是大多数时候在for 循环中将factor 增加2,除非factor 为2,因此序列将为2、3、5、7、9 , 11 等:

    for (int factor = 2; num > 1; factor += 1 + (factor & 1))

factor += 1 + (factor &amp; 1)factor 为偶数时将factor 递增1,在factor 为奇数时将factor 递增2,因此factor 的唯一偶数将是初始值2。

【讨论】:

  • 我添加了问题4并更新了代码。
  • 旁白:一个明确的速度改进会将迭代限制为num的平方根。
  • @chux-ReinstateMonica 我打算让 OP 考虑提速,但我添加了一些建议,包括基于您的平方根测试的建议。
  • 太棒了,谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-30
  • 1970-01-01
  • 1970-01-01
  • 2021-10-26
  • 1970-01-01
  • 2019-02-22
相关资源
最近更新 更多