我从Eular问题页面做了另一个问题。 10以下的素数之和是2 + 3 + 5 + 7 = 17。求出所有低于200万的素数之和。
我已经设法编写下面的代码,但是我认为在某个地方(即当我们遇到大的素数时)代码失去了准确性。 答案应该是142913828922,但我得到1179908154。
我不知道为什么我没有得到答案,因为下面的代码适用于10以下。
任何帮助将是伟大的。 我在做这些问题的原因是为了让C更好。
码:
#include <stdio.h> #include <stdlib.h> #include <math.h> /* Initialise */ void CalcNumber(unsigned long number); int isPrime(unsigned long number); /* Functions*/ void CalcNumber(unsigned long number) { unsigned long i = 1; unsigned long prime = 0; while(i != number) { i++; if(isPrime(i)) { printf("prime: %lu\n", i); prime += i; } } printf("The sum of primes under %lu: %lu\n",number, prime); printf("count: %d\n", i); } int isPrime(unsigned long number) { int i, nb, count, test,limit; test = count = 0; nb = number; limit = sqrt(nb) + 1; if(nb == 2) { return 1; } if (nb % 2 == 0) test = 1; else{ for (i = 3 ; i < limit && ! test; i+=2, count++) if (nb % i == 0) test = 1; } if (!test) return 1; else return 0; } int main(void) { unsigned long number; printf("Enter a number: \n"); scanf("%ul", &number ); CalcNumber(number); return EXIT_SUCCESS; }
考虑到数字的长度,你应该使用长度至少为64位的数据类型。 较新的C99标准包括至少64位的long long
(和unsigned long long
)数据类型。 如果你需要"%llu"
他们,你必须使用"%lld"
和"%llu"
。
void CalcNumber(unsigned long number) { unsigned long i = 1; unsigned long prime = 0; while(i != number) { i++; if(isPrime(i)) { printf("prime: %lu\n", i); prime += i; } }
请注意,您正在检查的数量大概是您需要的数量的两倍。 唯一偶数的素数是2
,所以除了大于或等于3
奇数之外,没有其他的检查点 – 并且手工添加1+2
。 你也可以用i += 2;
这里。
你的isPrime()
方法会重新计算大量的信息。 PE 真正得到的是使用Eratosthenes的Sieve来建立一个素数表,然后总结这个素数。
但是如果你真的想继续使用当前的isPrime()
方法,那么我想给出一个非常强烈的提示, 即当你知道一个数不是素数时,你完全放弃了test
变量并立即从方法return
。 这将导致代码更容易阅读和更容易调试。
考虑编写一些测试用例来测试isPrime()
。 检查一般疑犯:1,2,3,4,5,7,8,9,15,16,17等
存储素数总和的变量是无符号长整数,无符号长整数的范围是从0到4294967295。它不能包含142913828922数字。 142913828922 mod(4294967295 + 1)= 1179908154
改变你的数据类型