找出200万以下所有素数的总和。项目欧拉,C

时间:2013-08-09 23:58:29

标签: c

所以,一切似乎都运行良好,但程序没有给我正确的答案。我的是142,915,960,832,而应该是142,913,828,922。差异是2,131,910(如果我仍然可以减去纸上的数字哈哈),我不知道我从哪里获得这两百万。有谁可以帮助我?

#include <stdio.h>
#include <math.h>

#define BELOW 2000000

int isaprime (int num);

int main (void) {

    int i;
    float sum = 0;

    for (i = 2; i < BELOW; i++) {

            if (isaprime(i) == 1) {
                    sum = sum + i;
                    printf ("\n%d\t%.1f", i, sum);
            }
    }

    getch();
    return 0;
}

int isaprime (int num) {

    int i;

    for (i = 2; i <= sqrt(num); i++) {
            if (num % i == 0) {
                    return 0;
            }
            else {
                    ;
            }
    }

    return 1;
}

9 个答案:

答案 0 :(得分:9)

使用float作为sum是问题所在。最大整数k使得[-k, k]中的所有整数完全在32位浮点数中表示为2 ^ 24 1 ;之后你会开始失去一些整数的精度。因为你的总和超出了这个范围,所以你会失去精确度并且所有的赌注都会被关闭。

您需要更改为更大的类型,例如long(假设它在您的计算机上为64位)。做出改变,你会得到正确的答案(正如我对你的代码所做的那样):

[ec2-user@ip-10-196-190-10 ~]$ cat -n euler.c
     1  #include <stdio.h>
     2  #include <math.h>
     3  
     4  #define BELOW 2000000
     5  
     6  int isaprime (int num);
     7  
     8  int main (void) {
     9  
    10      int i;
    11      long sum = 0;
    12  
    13      for (i = 2; i < BELOW; i++) {
    14  
    15              if (isaprime(i) == 1) {
    16                      sum = sum + i;
    17              }
    18      }
    19      printf("sum: %ld\n", sum);
    20  
    21      return 0;
    22  }
    23  
    24  int isaprime (int num) {
    25  
    26      int i;
    27  
    28      for (i = 2; i <= sqrt(num); i++) {
    29              if (num % i == 0) {
    30                      return 0;
    31              }
    32              else {
    33                      ;
    34              }
    35      }
    36  
    37      return 1;
    38  }
[ec2-user@ip-10-196-190-10 ~]$ gcc euler.c -lm
[ec2-user@ip-10-196-190-10 ~]$ ./a.out
sum: 142913828922

1 :尾数中的23个显式位加上一个隐藏位。

答案 1 :(得分:5)

正如@LeeDanielCrocker所建议的,这是Sieve of Eratosthenes的一个实现,可以即时解决问题:

#include <stdio.h>
#include <string.h>

#define ISBITSET(x, i) (( x[i>>3] & (1<<(i&7)) ) != 0)
#define SETBIT(x, i) x[i>>3] |= (1<<(i&7));
#define CLEARBIT(x, i) x[i>>3] &= (1<<(i&7)) ^ 0xFF;

long long sumPrimes(int n) {
    char b[n/8+1];
    long long i, p;
    long long s = 0;

    memset(b, 255, sizeof(b));
    for (p=2; p<n; p++) {
        if (ISBITSET(b,p)) {
            //printf("%d\n", p);
            s += p;
            for (i=p*p; i<n; i+=p) {
                CLEARBIT(b, i); }}}
    return s; }

int main(void) {
    printf("%lld\n", sumPrimes(2000000));
    return 0; }

ideone,返回30毫秒。下面显示的优化版本仅在奇数和单独处理2上进行筛选,在ideone处以零时间(小于10毫秒)运行。

#include <stdio.h>
#include <string.h>

#define ISBITSET(x, i) (( x[i>>3] & (1<<(i&7)) ) != 0)
#define SETBIT(x, i) x[i>>3] |= (1<<(i&7));
#define CLEARBIT(x, i) x[i>>3] &= (1<<(i&7)) ^ 0xFF;

long long sumPrimes(int n) {
    int m = (n-1) / 2;
    char b[m/8+1];
    int i = 0;
    int p = 3;
    long long s = 2;
    int j;

    memset(b, 255, sizeof(b));

    while (p*p < n) {
        if (ISBITSET(b,i)) {
            s += p;
            j = (p*p - 3) / 2;
            while (j < m) {
                CLEARBIT(b, j);
                j += p; } }
        i += 1; p += 2; }

    while (i < m) {
        if (ISBITSET(b,i)) {
            s += p; }
        i += 1; p += 2; }

    return s; }

int main(void) {
    printf("%lld\n", sumPrimes(2000000));
    return 0; }

如果您对素数编程感兴趣,我在我的博客上谦虚地推荐这个essay;它描述了上面给出的两种算法,涵盖了解决Project Euler中素数问题所需的所有算法,并包含C语言和其他四种语言的源代码。

答案 2 :(得分:2)

请尝试这种方式,快速而简单:

int const MAX = 2000000;

int checkPrime(int n){
    int range = n;
    for (int i = 2; i < range; i++){
        if (n%i == 0){
            return 0;
        }
        range = n / i;
    }
    return 1;
}

int solution(){
    double sum = 0;
    for (int i = 2; i < MAX; i++){
        if (checkPrime(i) == 1){
            sum += i;
        }
    }
    return sum;
}

答案 3 :(得分:0)

#include<stdio.h>
#define MAX 2000001
long long a[MAX],c=0;
main()
{
     long long i=0,k,j,p,temp=0;
    long long inc=0;
    for(i=0;i<MAX;i++)
    a[i]=i;
    for(j=2;j*j<MAX;j++)
    {   
        temp=j;
        inc=2*temp;
        k=((MAX-1)/temp)-1;
        while(k)
        {
            printf("%d",inc);
            printf("\n");
            if(a[inc]!=0)
            a[inc]=0;
            inc+=temp;
            --k;
        }
    }
    for(p=0;p<MAX;p++)
    {
        if(a[p]!=0)
        c=c+a[p];

        printf("%lld",a[p]);
        printf("\n");
        }
    printf(" The sum is : %lld",c-1);
}

答案 4 :(得分:0)

您可以使用Sieve algorithm,因为这是最快的: -

在C ++中

std::vector<int> generate_primes( int n )
{
    std::vector<bool>sieve( n, true ) ;
    for( std::size_t i = 2 ; i < sieve.size() ; ++i ) if( sieve[i] )
          for( auto j = i*i ; j < sieve.size() ; j += i ) sieve[j] = false ;

    std::vector<int> primes ;
    for( std::size_t i = 2 ; i < sieve.size() ; ++i )
        if( sieve[i] ) primes.push_back(i) ;
    return primes ;
}

答案 5 :(得分:0)

虽然这个答案并不完美,但执行时间不到 3秒 C#中的代码

步骤1-省略了可被2,3,5,7整除的数字步骤2 - 要检查素数,我们不需要将给定的数字除以所有数字。使用平方根会将代码减少到一半。

    using System;


namespace ProjectEuler
{
    class Program
    {
        static void Main(string[] args)
        {
            long i, j, sum = 17;
            bool flag = true;
            for (i = 2; i < 2000000; i++)
            {
                if ((i % 2) != 0 && (i % 3) != 0 && (i % 5) != 0 && (i % 7) != 0)
                {
                    flag = true;
                    for (j = 2; j <= Math.Sqrt(i); j++)
                    {
                        if (i % j == 0)
                        {
                            flag = false;
                        }
                    }
                    if (flag == true)
                    {
                        sum = sum + i;
                    }
                }

            }
            Console.WriteLine(sum);
            Console.ReadLine();
        }
    }
}

答案 6 :(得分:0)

{{1}}

答案 7 :(得分:0)

这是我的javascript解决方案:

function sumPrimes(num) {

  // determine if a number is prime
  function isPrime(n) {
    if (n === 2) return true;
    if (n === 3) return true;
    if (n % 2 === 0) return false;
    if (n % 3 === 0) return false;

    var  i = 5;
    var  w = 2;
    while (i * i <= n) {
        if (n % i === 0) {
            return false;
        }
        i += w;
        w = 6 - w;
    }
    return true;
  }

  // subtract 1 for 'not being prime' in my context
  var sum = isPrime(num) ? num - 1 : -1;

  for (var x = 0; x < num; x++) {
    if (isPrime(x) === true) {
      sum += x;
    }
  }

  return sum;
}

答案 8 :(得分:-2)

您可以在c:

中查看以下代码
/*Program to print sum of all prime numbers upto 2000000*/

/*To check whether a number is prime or not it takes n^2 time by
  brute force but this program is sqrt(n) according to
  mathematical rules to check prime number efficiently.
*/

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define MAX 2000000
int main()
{
  int i,j;
  unsigned long int prod=0;
  int prime;
  for(i=2;i<=MAX;i++){
    prime=1;
    for(j=2;j<(int)(sqrt(i)+1);j++){
      if(i%j==0){
        prime=0;
        break;
      }
    }
    if(prime==1){
      prod=prod+i;
    }
  }
  printf("%ld",prod);
  return 0;
}