我的代码粘贴在下面。当我运行这个程序时,它继续计算。我正在使用旧的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;
}
答案 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秒。