我如何进行“数百万次计算?”

时间:2010-10-04 02:36:38

标签: c turbo-c

我的代码粘贴在下面。当我运行这个程序时,它继续计算。我正在使用旧的Turbo C ++编译器。这样的程序需要多长时间才能执行?我等了大约5分钟但是没有任何输出。

/*The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.

Find the sum of all the primes below two million.
*/
#include<stdio.h>
#include<conio.h>
#define TWO_MILLION 2*1000*1000
int IsPrime(long unsigned int num);
int main()
{
    long unsigned int i,sum=0;
    clrscr();
    for(i=2;i<TWO_MILLION;i++)
    {
        if(IsPrime(i))
        sum+=i;
    }
    gotoxy(25,25);
    printf("%ld",sum);
    getch();
    return 0;
}
int IsPrime(long unsigned int num)
{
    int flag=1;
    long unsigned int i;
    for(i=2;i<num;i++)
    {
        if(num%i==0)
        {
            flag=0;
            break;
        }
    }
    return flag;
}

10 个答案:

答案 0 :(得分:21)

你没有进行数百万次计算,你正在做数万亿次计算。

IsPrime将在O(n)时间运行,即它将执行200万条指令以确定该单个数字。做两百万次这样的事情将花费太长时间。

要做到这一点,你真的想使用像http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes这样的东西,它可以更有效地确定特定范围内的所有素数。

答案 1 :(得分:3)

  

这样的程序需要多长时间才能执行?

这完全取决于您的平台。我怀疑,因为你正在进行〜(两百万)^ 2次操作(~4万亿次)计算,这是一段非常长的时间。

有更好的方法来执行你正在做的事情 - 例如检查素数你只需要检查数字的平方根,而不是一直到数字本身。更不用说可能有一个动态编程解决方案可以比这快得多。

答案 2 :(得分:3)

正如其他人所说,这需要很长时间。另一种有趣的方法是Eratosthenes的Sieve。您可以在以下网址阅读:

http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

基本上你用数字2到2百万来初始化一个数组。尚未处理的最低数字是素数。然后,从阵列中删除此数字的所有倍数并继续。它会比你拥有的速度快得多。

答案 3 :(得分:3)

不合时宜的回答

gotoxy(25,25);

您是否以文本模式运行程序?如果文本屏幕仅为80 x 25,并且如果第25行被某些其他内容遮挡,那么您很可能在文本屏幕中看不到任何更改。

答案 4 :(得分:2)

正如其他人所说:检查实施的限制

如果TurboC++具有&lt; limits.h&gt;,则这些实施限制在该标头中定义了相应的宏

#include <limits.h>
#include <stdio.h>
int main(void) {
    printf("int goes from %d to %d.\n", INT_MIN, INT_MAX);
    printf("long goes from %ld to %ld.\n", LONG_MIN, LONG_MAX);
    return 0;
}

如果失败,您需要自己“计算”限制。我正在切换到unsigned,因为它们没有溢出问题,我只需要“计算”上限(下限为0)

#include <stdio.h>
int main(void) {
    unsigned u;
    unsigned long lu;

    u = -1; lu = -1;
    printf("unsigned ints go all the way to %u\n", u);
    printf("unsigned longs go all the way to %lu\n", lu);
    return 0;
}

在我的系统上,第一个程序输出

int goes from -2147483648 to 2147483647.
long goes from -9223372036854775808 to 9223372036854775807.

和第二个程序输出

unsigned ints go all the way to 4294967295
unsigned longs go all the way to 18446744073709551615

答案 5 :(得分:2)

除了“史诗”之外,仍然没有关于常数的评论/答案......

#define TWO_MILLION 2*1000*1000

这很糟糕。稍后更改值时,您要么具有名称 - 内容不匹配:

#define TWO_MILLION 5*1000*1000

或者将其重命名为

#define FIVE_MILLION 5*1000*1000

并且需要在您使用它的任何地方进行更改。不要在内容之后命名常量,这只是将你的魔法数字变成魔法名字。在它们的含义后命名它们,例如MAX_NUMBER UPPER_LIMIT RANGE_TO_TEST或其他最适合的内容。

答案 6 :(得分:1)

你可以使用筛选方法来做到这一点,这并不比你使用的方法复杂得多。我们的想法是选择前n个连续素数并用它们构建一个筛子。我在my answer中讨论了(带有证据)另一个问题,Sheldon L. Cooper在his中提供了一个实现。我认为他没有得到足够的赞成票(我已经得到了'很好的回答',所以也许你可以帮助他。)

因此,在计算筛号后,您只需要通过与筛子对齐并且小于n的平方根的数字来测试可分性。

答案 7 :(得分:0)

这可能需要非常长时间才能运行。

添加此项以查看您的进度(虽然需要更长时间):

for(i=2;i<num;i++)
    {
        if(num%i==0)
        {
            flag=0;
            printf("%d,", num); /* <== show the prime */
            break;
        }
    }

修改

正如其他人指出的那样,这是计算素数的最慢方法。你的任务的目的可能是让你更快地查找(并实施)它?

答案 8 :(得分:0)

您的程序导致整数溢出,您可以使用long long来修复它。

此外,检查数字是否为素数的算法不是很好。另一种同样容易的方法是将数字2测试到数字的平方根。您只需要检查数字的平方根,以确定它是否为素数。

答案 9 :(得分:0)

一个简单的改变会告诉你程序的运行速度,以及它需要做多少工作。每100次迭代就可以轻松打印出您的状态。 (或者您可以将其设置为1000或10000次迭代。)


认识到您可以在<{1}}中 DOUBLE 循环速度。
检查2后,您只需要检查奇数,并且可以使用IsPrime代替i+=2

如果你担心速度,你为什么要花这么多时间检查数字? (请注意,一旦开始只做奇数,你还需要将输出测试更改为奇数)

您可以双倍 i++中的循环速度,同时避免在那里使用偶数。 (再次,你必须使用特殊情况2,然后使用i + = 2,从3开始获得3,5,7,9 ......)

通过使main中的循环运行速度提高两倍,并使IsPrime中的循环运行速度提高两倍,这将使您的程序更快地 4X 。 (如果它花了一个小时,现在它将是15分钟。)


您可以进行的另一项重大改进只是将循环运行到main,而不是sqrt(num)

由于我讨厌引入浮点函数,例如num,我建议使用近似的近似值,它会在传递sqrt边界的100次迭代中停止,并且还会定期显示状态更新。

sqrt

P.S。我将此代码放入C#项目(次要移植)。 当然,现在它运行在64位操作系统上,具有更好的编译器和2.8GHz CPU 它跑了不到20秒。