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

发布于 2024-09-25 19:04:16 字数 772 浏览 3 评论 0原文

我的代码粘贴在下面。当我运行这个程序时,它一直在计算。我使用的是旧的 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;
}

My code is pasted below.When I run this program,it keeps on calculating.I am using the old Turbo C++ compiler.How much time should such a program take to execute?I waited about 5 minutes but there wasn't any output.

/*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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

雨落□心尘 2024-10-02 19:04:16

你不是在进行数百万次计算,而是在进行数万亿次计算。

IsPrime 将在 O(n) 时间内运行,也就是说,它会执行 200 万条指令来确定单个数字。做这种事情两百万次会花费太长时间。

为此,您确实需要使用类似以下内容的内容: http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes< /a>,它可以更有效地确定特定范围内的所有素数。

You aren't doing millions of calculations, you are doing trillions of them.

IsPrime will run in O(n) time, that is it will perform 2 million instructions just to determine that single number. Doing that sort of thing two millions time will take way too long.

To do this you really want to use something like: http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes, which can much more efficently determine all of the prime numbers in a particular range.

懒猫 2024-10-02 19:04:16

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

这完全取决于您的平台。我怀疑,由于您正在执行〜(两百万)^ 2 次操作(〜四万亿)计算,所以时间太长了。

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

How much time should such a program take to execute?

That depends completely on your platform. I suspect since you're performing ~(two million)^2 operations (~four trillion) calculations, an awful long time.

There are much better ways to perform what you're doing -- for example to check prime you only need to check to the square root of the number, not all the way up to the number itself. Not to mention there is probably a dynamic programming solution which can do it much much faster than that.

半寸时光 2024-10-02 19:04:16

正如其他人所说,这需要很长时间。另一种有趣的方法是埃拉托斯特尼筛法。您可以在以下位置阅读相关内容:

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

基本上您用数字 2...2 百万初始化一个数组。尚未处理的最小数是质数。然后,从数组中删除该数字的所有倍数并继续。它会比你的运行速度快得多。

As others have said, it will take a long time. One alternate and interesting approach is the Sieve of Eratosthenes. You can read about it at:

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

Basically you initialize an array with the numbers 2...2 million. The lowest number not yet processed is prime. Then, you remove all multiples of this number from the array and continue. It will run much faster than what you have.

我的鱼塘能养鲲 2024-10-02 19:04:16

另类答案

gotoxy(25,25);

您是否以文本模式运行程序?如果文本屏幕只有 80 x 25,并且第 25 行被其他东西遮挡,那么您很可能不会在文本屏幕中看到任何变化。

Off-beat answer

gotoxy(25,25);

Do you run your program in text mode? If the text screen is only 80 x 25, and if the 25th line is occluded by some other things, then chances are you won't see any change in the text screen.

jJeQQOZ5 2024-10-02 19:04:16

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

如果TurboC++具有,则这些实现限制在该标头中定义了相应的宏

#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;
}

如果这失败了您需要自己“计算”限制。我正在切换到无符号,因为它们没有溢出问题,我只需要“计算”上限(下限为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

As others have said: check the limits of your implementation

If TurboC++ has <limits.h>, those implementation limits have a corresponding macro defined in that header

#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;
}

If that fails you need to "calculate" the limits yourself. I'm switching to unsigned because there's no overflow problem with them, and I only need to "calculate" the upper limit (the lower limit is 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;
}

On my system, the 1st program outputs

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

and the 2nd program outputs

unsigned ints go all the way to 4294967295
unsigned longs go all the way to 18446744073709551615
疯到世界奔溃 2024-10-02 19:04:16

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

#define TWO_MILLION 2*1000*1000

这很糟糕。当您稍后更改该值时,您要么会出现 name-content-mismatch:

#define TWO_MILLION 5*1000*1000

,要么将其重命名为

#define FIVE_MILLION 5*1000*1000

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

Still no comment/answer about the constant except an "Epic"...

#define TWO_MILLION 2*1000*1000

This is bad. When you change the value later, you either have a name-content-mismatch:

#define TWO_MILLION 5*1000*1000

or you rename it to

#define FIVE_MILLION 5*1000*1000

and need to change it everywhere you've used it. Don't name your constants after the content, this just turns your magic numbers into magic names. Name them after their meaning, e.g. MAX_NUMBER UPPER_LIMIT RANGE_TO_TEST or whatever fits best.

九命猫 2024-10-02 19:04:16

您也可以使用筛选方法来执行此操作,该方法并不比您使用的方法复杂多少。这个想法是选择前 n 个连续素数并用它们构建一个筛子。我在我对另一个问题的回答中讨论了它(带有证据) Sheldon L. Cooper 在 his 中提供了一个实现。我认为他这样做没有得到足够的支持(我已经得到了“很好的答案”,所以也许你可以帮助他解决这个问题。

所以在计算出筛数之后,你只需要测试被该行的数字整除与筛子一起,并且小于n的平方根。

you can use sieve methods to do this as well that aren't much more complicated than what you are using. The idea is to pick the first n consecutive prime numbers and use them to construct a sieve. I discuss it (with proofs) in my answer to another question and Sheldon L. Cooper provides an implementation in his. I don't think he got enough upvotes for doing so (I already got 'nice answer', so maybe you could help him out on that.

so after you calculate the sieve numbers, you only need to test for divisibility by numbers that line up with the sieve and are smaller than the square root of n.

你丑哭了我 2024-10-02 19:04:16

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

添加此内容以查看您的进度(尽管需要更长的时间):

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

编辑

正如其他人指出的那样,这是计算素数的最慢方法。也许您的任务的目的是让您查找(并实现)更快的任务?

This could take a very long time to run.

Add this to see your progress (though it will take even longer):

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

Edit

As others are pointing out, this is the slowest way to count primes. Perhaps the purpose of your assignment is to get you to look up (and implement) faster ones?

几度春秋 2024-10-02 19:04:16

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

另外,您检查数字是否为素数的算法也不是很好。另一种同样简单的方法是测试数字 2 的平方根。您只需检查数字的平方根即可确定它是否为素数。

Your program results in integer overflow, you could use long long to fix it.

Also, your algorithm for checking if a number is prime is not very good. Another way that is just as easy is to test the numbers 2 to the square root of the number. You only have to check up to the square root of the number to determine if it is prime.

维持三分热 2024-10-02 19:04:16

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


认识到您可以将 IsPrime 中的循环速度加倍
检查 2 后,只需检查奇数即可,并且可以使用 i+=2 而不是 i++ 前进。

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

您可以将 main 中的循环速度双倍也避免那里有偶数。 (同样,您必须特殊情况 2,然后使用 i+=2,从 3 开始得到 3, 5, 7, 9....)

通过使 IsPrime 中的循环运行两次快,并使 main 中的循环运行速度提高一倍,这将使您的程序运行速度 4 倍。 (如果以前需要一个小时,现在则需要 15 分钟。)


您可以做出的另一个重大速度改进是仅将循环运行到 sqrt(num),而不是 num

由于我讨厌引入浮点函数,例如 sqrt,因此我建议使用一个近似值,该近似值将在通过 sqrt 边界的 100 次迭代内停止,并且还会定期显示状态更新。

if (num%2 == 0)
{
    flag=0;
    return flag;
}

/* Now that we checked 2, we only need to check odd numbers from now on. */
for(i=3;i<num;i+=2)
{
    if (i%101 == 0)
    {
        printf("i is %d out of %d\n", i, num);
        if (i*i > num)
        {
            break;  /* If you pass the sqrt boundary, quit. */
        }
    }

    if(num%i==0)
    {
        flag=0;
        break;
    }
}

PS 我将此代码放入 C# 项目中(较小的移植)。
当然,它现在运行在 64 位操作系统上,具有更好的编译器和 2.8GHz CPU。
运行时间不到 20 秒。

A simple change would show you how fast your program is running, and how much work it has to do. It is easy to print out your status around every 100 iterations.
(Or you could set it to 1000, or 10000 iterations.)


Recognize that you could DOUBLE the speed of your loop in IsPrime.
After you check 2, you only need to check odd numbers, and could advance with i+=2 instead of i++.

If you're concerned about speed, why are you spending so much time checking even numbers?
(note that once you start doing only odd-numbers, you also need to change the output test to be a odd number)

You can DOUBLE the speed of the loop in main as well by also avoiding even numbers there. (again, you have to special-case 2, then use i+=2, starting at 3 to get 3, 5, 7, 9....)

By making the loop in IsPrime run twice as fast, and making the loop in main run twice as fast, this should make your program go 4X faster. (if it would've taken an hour before, now it'll be 15 minutes.)


The other big speed improvement you could make is only running the loop to sqrt(num), instead of num

Since I hate bringing in floating point functions, such as sqrt, I instead suggest a close approximation that will stop within 100 iterations of passing the sqrt boundary, and also show status updates regularly.

if (num%2 == 0)
{
    flag=0;
    return flag;
}

/* Now that we checked 2, we only need to check odd numbers from now on. */
for(i=3;i<num;i+=2)
{
    if (i%101 == 0)
    {
        printf("i is %d out of %d\n", i, num);
        if (i*i > num)
        {
            break;  /* If you pass the sqrt boundary, quit. */
        }
    }

    if(num%i==0)
    {
        flag=0;
        break;
    }
}

P.S. I put this code into a C# project (minor porting).
Granted, this was now running on a 64-bit OS, with a better compiler and 2.8GHz CPU.
It ran in less than 20 seconds.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文