你在我提供的代码之间选择一个代码而不是另一个代码的原因是什么?有什么建议可以改善它们吗?

时间:2017-05-15 20:30:25

标签: c algorithm performance time-complexity

下面的程序会计算出可以被1到20之间的所有数字整除的最小正数。您可以在两者中选择哪一个,为什么? 第一段代码:

#include <stdio.h>

#define ulong unsigned long

int main(void)
{
const ulong val = 20;
ulong x;
ulong y;

for (x = val; ; x += val)
{
    for (y = val - 1; y; y--)
    {
        if (x % y != 0)
        {
            break;
        }
    }

    if (y == 0)
    {
        printf("Answer = %u \n", x);
        break;
    }
}
return 0;
}

第二段代码:

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

bool isDivisable(int x);

int main()
{
    int a = 20;
    while (true)
    {
        a+=20;
        if (isDivisable(a))
        {
            break;
        }
    }
    printf("%d\n", a);
    system("pause");
    return 0;
}

bool isDivisable(int x)
{
    for (int i = 11; i < 21; i++)
    {
        if (x%i != 0)return false;

    }
    return true;
}

此外,这个for循环代表什么?: for(y = val - 1; y; y--) 它会迭代直到达到到底是什么程度?代码(y = val - 1 ;; y--)会产生相同的结果吗?

3 个答案:

答案 0 :(得分:1)

您要查找的数字是从1到20的所有数字的 least common multiple (LCM)。在这种情况下,LCM将等于乘以最高的乘积数字素数因子化中每个素数除数的幂。

因此,结果将等于2^4 * 3^2 * 5 * 7 * 11 * 13 * 17 * 19 = 232792560

如果您想查找从1N的所有数字的LCM,您只需使用 sieve of Eratosthenes 查找{{1}中的所有素数} {}} 1或选择更优化的算法。 C中的示例(重写代码的第一个代码):

N

答案 1 :(得分:0)

这可能是需要考虑的其他因素:

// The least common multiple of numbers from 1 to 20.
// 2^4 * 3^2 * 5 * 7 * 11 * 13 * 17 * 19 = 232792560
// See also https://oeis.org/A003418 for details.
int lcm1_20() {
    return 232792560
}

如果您只对相应的值感兴趣(并且您不打算更改参数“20”),那么使用预先计算的值和解释性注释可能就足够了。

在您提供的两个代码中,我会选择第一个代码,主要是因为以下几个方面使第二个版本看起来不太专业:

  • 第二个代码不一致地使用空格,例如a+=20,vs int a = 20;;还if (x%i != 0)return false; - 我觉得返回之前的空格看起来更好;
  • 方法名称isDivisable包含拼写错误。

答案 2 :(得分:-1)

循环'for(y = val - 1; y; y--)'将在y不为0时循环。你的另一个例子永远不会退出。

我更喜欢你提出的第一个算法,因为它消除了不必要的函数调用,并且更易于阅读和理解。