goldbach.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /***********************************************************
  2. * Program to check the Goldbach's conjecture solution *
  3. * written by Zoltan Baldaszti Tue Jan 8 22:03:06 CET 2008 *
  4. * the mathematical background and all coding was done by *
  5. * the author, all rights reserved to him. *
  6. * Contact: zoltan DOT baldaszti AT gmail.com *
  7. * *
  8. * Goldbach's conjecture: all even numbers (>2) can be *
  9. * represented by an addititon of two primes. *
  10. * This program is reponsible for checking if the given *
  11. * prime indexing method fulfill this or not. *
  12. * *
  13. * Compile: gcc goldbach.c -o goldbach *
  14. * Usage: ./goldbach (num of primes) *
  15. ***********************************************************/
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <time.h>
  19. //global variables
  20. long argument; //required number of primes
  21. long *primes=NULL; //array to hold the primes
  22. long num_primes=0; //number of elements in primes array
  23. //this function checks if n is a prime, if so, then stores it in primes array
  24. //prime check is done by dividing n with all number in primes array
  25. void is_prime(long n)
  26. {
  27. long prime=0,i,third;
  28. //even number can't be a prime (we exclude 2 also, but this is what we want!)
  29. if(n%2==0) return;
  30. //shortcut for the first 4 primes
  31. if(n==1 || n==3 || n==5 || n==7) prime=n;
  32. else {
  33. //we do the fastest method possible: we use the primes already found
  34. //to determine wether the given n is a prime or not. Obviously, since
  35. //it's an odd number, it's enough to check primes not larger than
  36. //the number divided by 3.
  37. prime=n; third=n/3;
  38. for(i=1;i<num_primes && primes[i]<=third;i++) if(n%(primes[i])==0) { prime=0; break; }
  39. }
  40. //if it's a prime, append it to our list
  41. if(prime){
  42. primes=realloc(primes,(num_primes+1)*sizeof(long));
  43. primes[num_primes]=prime;
  44. num_primes++;
  45. }
  46. }
  47. //function to generate primes. It also uses a cache in file "primes.txt"
  48. //if less prime required than loaded from cache, does nothing.
  49. void generateprimes()
  50. {
  51. long i;
  52. FILE *f;
  53. f=fopen("primes.txt","r");
  54. if(f){
  55. while(!feof(f)) {
  56. fscanf(f,"%ld\n",&i);
  57. if(i>0){
  58. primes=realloc(primes,(num_primes+1)*sizeof(long));
  59. primes[num_primes++]=i;
  60. if(num_primes==argument) break;
  61. }
  62. }
  63. fclose(f);
  64. }
  65. printf("Loaded %ld primes.\n",num_primes);
  66. if(num_primes<argument){
  67. time_t s=0,e=0;
  68. printf("Generating %ld more primes... ",(argument-num_primes)); fflush(stdout);
  69. time(&s);
  70. for(i=(num_primes?primes[num_primes-1]+2:1);num_primes<argument;i+=2) is_prime(i);
  71. time(&e);
  72. f=fopen("primes.txt","w+");
  73. for(i=0;i<num_primes;i++) fprintf(f,"%ld\n",primes[i]);
  74. fclose(f);
  75. printf("OK (%d secs)\n",(int)(e-s));
  76. }
  77. //sanity check (not necessary, but be paranoid)
  78. if(argument<num_primes) num_primes=argument;
  79. }
  80. //the main function
  81. int main(int argc,char **argv)
  82. {
  83. //---variables
  84. //i=universal index
  85. //j,k=indexes to primes array
  86. //even=the calculated even number
  87. //max=the largest even number calculated
  88. long i,j=0,k=1,max=2,even=0;
  89. //---variables to check the result
  90. //seg=the 8 bit block where the boolean flags reside
  91. //offs=offset in the seg-th block
  92. //lastseg=the last segment (required to allocate appropirate amount of memory)
  93. //check=array where the boolean values are stored
  94. //mask=2^1,2^2,...,2^7 stored in an array for speed up
  95. long seg=0,offs=0,lastseg=-1;
  96. unsigned char *check=NULL,mask[]={1,2,4,8,16,32,64,128};
  97. //if we have an argument then use it, if not, ask for it
  98. if(argv[1]!=NULL) argument=strtol(argv[1],NULL,10);
  99. else {
  100. printf("Number of primes to use? ");
  101. scanf("%ld",&argument);
  102. }
  103. //generate the primes we'll use
  104. generateprimes();
  105. //print status header
  106. printf("%11s%9s%9s%11s%11s%11s\n","i","j","k","p(j)","p(k)","p(j)+p(k)");
  107. //main loop. Note that the exit condition depends on k, not i
  108. //here we calculate even number by adding two primes and set
  109. //a flag to indicate that the even number is in Rf.
  110. for(i=0;k<num_primes;i++){
  111. //get the even number
  112. even=primes[j]+primes[k];
  113. //print status
  114. printf("%11ld%9ld%9ld%11ld%11ld%11ld%5ld%%\r",i,j,k,primes[j],primes[k],even,(k+1)*100/num_primes);
  115. //calculate the next indexes (the point of all) - it's beautiful, how simple it is
  116. //Note, that if (2), max will contain the last value of
  117. //a B(k) set, therefore as larger argument you gave, the larger number of
  118. //even numbers will be missing. But, max(B(k))>min(B(k+1)) and we can garantee
  119. //that only even numbers less than min(B(k+1)) will be generated
  120. j++; if(j==k) {
  121. j=0; k++;
  122. //(1)
  123. if(max<primes[j]+primes[k]) max=primes[j]+primes[k];
  124. }
  125. //(2)
  126. /*if(max<primes[j]+primes[k]) max=primes[j]+primes[k];*/
  127. //finally set the number-has-been-calculated flag to true.
  128. seg=(even-2)/16; offs=((even-2)/2)%8;
  129. if(seg>lastseg) { check=realloc(check,seg+1); check[seg]=0; lastseg=seg; }
  130. check[seg]|=mask[offs];
  131. }
  132. printf("\nLast prime:%ld largest even number:%ld\nChecking. Missing:",primes[k-1],max);
  133. //do a check: have we generated all even numbers in interval [4,max] or not?
  134. //if so, it means that we can represent every even number by adding two primes
  135. //therefore Goldbach's conjecture is no longer an unsolved problem.
  136. j=0;
  137. for(i=4;i<=max;i+=2){
  138. seg=(i-2)/16; offs=((i-2)/2)%8;
  139. if(seg>lastseg || !(check[seg]&mask[offs])) { j++; printf(" %ld",i); }
  140. }
  141. //print the result of the check
  142. if(j==0) printf(" none.\nCorrect, all even numbers in [4,%ld] have been generated.\n",max);
  143. else printf("\nNot correct, %ld even number(s) missing.\n",j);
  144. exit(j);
  145. }