Connecting Tech Pros Worldwide Forums | Help | Site Map

Prime Numbers

rhle.freak
Guest
 
Posts: n/a
#1: Jan 6 '07
Here is my code to generate prime numbers.It works absolutely fine when
the range is
*not very large*. However on initializing i with a large integer it
produces erroneous results
(some numbers ending in 5 ..which obviously cannot be prime numbers)
can anyone please help me out with the reason??


/*Generate Prime Numbers*/
#include<stdio.h>
#include<stdlib.h>

struct node{
int data;
struct node *next;
};

node* create_node(void)
{
struct node *z;
z=(node*)malloc(sizeof(node));
if(z==NULL)
{
printf("Error");
exit(0);
}
return z;
}

node* node_insert(struct node *start,int prime_num)
{
struct node *z;
z=create_node();
z->data=prime_num;
z->next=start;
start=z;

return start;

}

int main(void)
{
int flag;
unsigned /*long long*/ int i;
struct node *start=NULL,*j;

for(i=2;i<20000;i++) /*Range to check*/
{
flag=0;
for(j=start;j!=NULL;j=j->next) /*Call the prime numbers from
the stack*/
{
if(i%j->data==0 || i%2==0)
flag=1;
}
if(flag==0)
{
start=node_insert(start,i); /*Push the generated prime numbers into
the stack*/
printf("%d\n",i);
}
}
return 0;
}


niklaus@gmail.com
Guest
 
Posts: n/a
#2: Jan 6 '07

re: Prime Numbers



rhle.freak wrote:
Quote:
Here is my code to generate prime numbers.It works absolutely fine when
the range is
*not very large*. However on initializing i with a large integer it
produces erroneous results
(some numbers ending in 5 ..which obviously cannot be prime numbers)
can anyone please help me out with the reason??
>
>
/*Generate Prime Numbers*/
#include<stdio.h>
#include<stdlib.h>
>
struct node{
int data;
struct node *next;
};
>
typedef is needed in C not in C++
Quote:
node* create_node(void)
{
struct node *z;
z=(node*)malloc(sizeof(node));
if(z==NULL)
{
printf("Error");
exit(0);
}
return z;
}
>
node* node_insert(struct node *start,int prime_num)
{
struct node *z;
z=create_node();
z->data=prime_num;
z->next=start;
start=z;
>
return start;
>
}
>
int main(void)
{
int flag;
unsigned /*long long*/ int i;
struct node *start=NULL,*j;
>
for(i=2;i<20000;i++) /*Range to check*/
{
flag=0;
for(j=start;j!=NULL;j=j->next) /*Call the prime numbers from
the stack*/
{
if(i%j->data==0 || i%2==0)
flag=1;
}
if(flag==0)
{
start=node_insert(start,i); /*Push the generated prime numbers into
the stack*/
printf("%d\n",i);
}
}
return 0;
}
I ran it and found primes until 20000 fine. Well can you tell me for
which testcase it fails which value of i it fails. One reason could be
overflow .Otherwise it looks fine

Moreover do a for(i=3;i< MAX ;i+=2)

Barry Schwarz
Guest
 
Posts: n/a
#3: Jan 6 '07

re: Prime Numbers


On 6 Jan 2007 06:37:51 -0800, "rhle.freak" <rhle.freak@gmail.com>
wrote:
Quote:
>Here is my code to generate prime numbers.It works absolutely fine when
>the range is
>*not very large*. However on initializing i with a large integer it
>produces erroneous results
>(some numbers ending in 5 ..which obviously cannot be prime numbers)
>can anyone please help me out with the reason??
After correcting the syntax error noted below, your code ran fine.
Which large value of i had a problem? Show the exact code.

Did the problem occur only when you removed the comments around the
long long in the definition of i? If so, did you remember to change
both the declaration of the struct and the conversion specifier in the
printf format string?
Quote:
>
>
> /*Generate Prime Numbers*/
>#include<stdio.h>
>#include<stdlib.h>
>
>struct node{
> int data;
> struct node *next;
>};
>
>node* create_node(void)
There is no type node in this translation unit.
Quote:
>{
> struct node *z;
> z=(node*)malloc(sizeof(node));
Don't cast the return from malloc.
Quote:
> if(z==NULL)
> {
> printf("Error");
> exit(0);
> }
> return z;
>}
>
>node* node_insert(struct node *start,int prime_num)
>{
> struct node *z;
> z=create_node();
> z->data=prime_num;
> z->next=start;
> start=z;
>
> return start;
>
>}
>
>int main(void)
>{
> int flag;
> unsigned /*long long*/ int i;
> struct node *start=NULL,*j;
>
> for(i=2;i<20000;i++) /*Range to check*/
> {
> flag=0;
> for(j=start;j!=NULL;j=j->next) /*Call the prime numbers from
>the stack*/
> {
> if(i%j->data==0 || i%2==0)
Since 2 was the first number added to the stack, the second relational
expression is superfluous.
Quote:
> flag=1;
> }
> if(flag==0)
> {
> start=node_insert(start,i); /*Push the generated prime numbers into
>the stack*/
> printf("%d\n",i);
> }
> }
> return 0;
>}

Remove del for email
james of tucson
Guest
 
Posts: n/a
#4: Jan 6 '07

re: Prime Numbers


rhle.freak wrote:
Quote:
Here is my code to generate prime numbers.It works absolutely fine when
the range is
*not very large*. However on initializing i with a large integer it
produces erroneous results
(some numbers ending in 5 ..which obviously cannot be prime numbers)
can anyone please help me out with the reason?
Your code needs this to compile:

typedef struct node node;

Does the problem appear when using long variables, and are you using the
"L" suffix on constants?

What you posted does not appear to duplicate your problem.
CBFalconer
Guest
 
Posts: n/a
#5: Jan 6 '07

re: Prime Numbers


"rhle.freak" wrote:
Quote:
>
Here is my code to generate prime numbers.It works absolutely fine
when the range is *not very large*. However on initializing i with
a large integer it produces erroneous results (some numbers ending
in 5 ..which obviously cannot be prime numbers) can anyone please
help me out with the reason??
.... snip code ...

I passed your code through indent to make it legible (too big
indentations, line wraps), which worked properly since you avoided
the error of using // comments. Good for you. It makes it easy
for someone to test the code. The result is below, together with
the errors shown up on compilation:

/* Generate Prime Numbers */
#include<stdio.h>
#include<stdlib.h>

struct node {
int data;
struct node *next;
};

node *create_node(void)
{
struct node *z;

z = (node *) malloc(sizeof(node));
if (z == NULL) {
printf("Error");
exit(0);
}
return z;
}

node *node_insert(struct node * start, int prime_num)
{
struct node *z;

z = create_node();
z->data = prime_num;
z->next = start;
start = z;

return start;
}

int main(void)
{
int flag;
unsigned /*long long */ int i;
struct node *start = NULL, *j;

for (i = 2; i < 20000; i++) { /*Range to check */
flag = 0;
for (j = start; j != NULL; j = j->next) {
/*Call the prime numbers from the stack */
if (i % j->data == 0 || i % 2 == 0)
flag = 1;
}
if (flag == 0) {
start = node_insert(start, i);
/* Push the generated prime numbers into the stack */
printf("%d\n", i);
}
}
return 0;
}

[1] c:\c\junk>cc junk.c
junk.c:10: parse error before '*' token
junk.c:11: warning: return type defaults to `int'
junk.c: In function `create_node':
junk.c:14: `node' undeclared (first use in this function)
junk.c:14: (Each undeclared identifier is reported only once
junk.c:14: for each function it appears in.)
junk.c:14: parse error before ')' token
junk.c:19: warning: return from incompatible pointer type
junk.c: At top level:
junk.c:22: parse error before '*' token
junk.c:23: warning: return type defaults to `int'
junk.c: In function `node_insert':
junk.c:26: warning: assignment from incompatible pointer type
junk.c:31: warning: return from incompatible pointer type
junk.c: In function `main':
junk.c:48: warning: assignment from incompatible pointer type

Your biggest error is assuming node is a type. The type name is
"struct node".

After correcting lines 10, 12, 14, and 22 to the following, it
compiles. You should never cast the return value from malloc.
Every cast is a potential unflagged error and you should know
precisely why you are doing it. After that it appears to run
correctly. You should turn up your compiler warning level.

struct node *create_node(void)
{
struct node *z;

z = malloc(sizeof(*z));
if (z == NULL) {
printf("Error");
exit(0);
}
return z;
}

struct node *node_insert(struct node * start, int prime_num)

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>


David T. Ashley
Guest
 
Posts: n/a
#6: Jan 6 '07

re: Prime Numbers


"CBFalconer" <cbfalconer@yahoo.comwrote in message
news:459FE705.37EA4C0C@yahoo.com...
Quote:
I passed your code through indent to make it legible (too big
indentations, line wraps), which worked properly since you avoided
the error of using // comments. Good for you. It makes it easy
for someone to test the code. The result is below, together with
the errors shown up on compilation:
There is a program called "indent"? Sounds useful. Where can I get a copy
for my Linux and Windows boxes?


Cactus
Guest
 
Posts: n/a
#7: Jan 6 '07

re: Prime Numbers



rhle.freak wrote:
Quote:
Here is my code to generate prime numbers.It works absolutely fine when
the range is
*not very large*. However on initializing i with a large integer it
produces erroneous results
(some numbers ending in 5 ..which obviously cannot be prime numbers)
can anyone please help me out with the reason??
Others have pointed out errors in your code but I am puzzled by your
use of the term 'initialisation' for i.

Currently i is initialised to 2 here:
Quote:
for(i=2;i<20000;i++) /*Range to check*/
and this will ensure that the loop identifies and stores all primes
from 2 upwards.

But if, as you suggest, you initialise i to a large integer value
rather than 2, your loop will not then identify and store primes that
are less than this initial i value and this will mean that some higher
values will be wrongly identified as primes.

Can you indicate the exact code that outputs wrong prime values?

Cactus

Xian
Guest
 
Posts: n/a
#8: Jan 6 '07

re: Prime Numbers


rhle.freak wrote:
Quote:
flag=0;
for(j=start;j!=NULL;j=j->next) * * * /*Call the prime numbers from
the stack*/
{
if(i%j->data==0 || i%2==0)
flag=1;
}
for(j=start;j!=NULL&&flag==0;j=j->next) //will stop you testing after you
know its not a prime

--
/Xian
Keith Thompson
Guest
 
Posts: n/a
#9: Jan 6 '07

re: Prime Numbers


Barry Schwarz <schwarzb@doezl.netwrites:
[...]
Quote:
Quote:
> /*Generate Prime Numbers*/
>>#include<stdio.h>
>>#include<stdlib.h>
>>
>>struct node{
>> int data;
>> struct node *next;
>>};
>>
>>node* create_node(void)
>
There is no type node in this translation unit.
[...]

Which leads me to suspect he's compiling it with a C++ compiler.
(Otherwise I'd assume he'd posted something other than his actual
code.)

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Keith Thompson
Guest
 
Posts: n/a
#10: Jan 6 '07

re: Prime Numbers


"David T. Ashley" <dta@e3ft.comwrites:
Quote:
"CBFalconer" <cbfalconer@yahoo.comwrote in message
news:459FE705.37EA4C0C@yahoo.com...
Quote:
>I passed your code through indent to make it legible (too big
>indentations, line wraps), which worked properly since you avoided
>the error of using // comments. Good for you. It makes it easy
>for someone to test the code. The result is below, together with
>the errors shown up on compilation:
>
There is a program called "indent"? Sounds useful. Where can I get a copy
for my Linux and Windows boxes?
Your Linux box probably already has it. I'm not sure about Windows,
but you can obtain the sources for GNU Indent from
<ftp://ftp.gnu.org/gnu/indent/>.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
CBFalconer
Guest
 
Posts: n/a
#11: Jan 7 '07

re: Prime Numbers


"David T. Ashley" wrote:
Quote:
"CBFalconer" <cbfalconer@yahoo.comwrote in message
>
Quote:
>I passed your code through indent to make it legible (too big
>indentations, line wraps), which worked properly since you avoided
>the error of using // comments. Good for you. It makes it easy
>for someone to test the code. The result is below, together with
>the errors shown up on compilation:
>
There is a program called "indent"? Sounds useful. Where can I
get a copy for my Linux and Windows boxes?
[1] c:\c\junk>indent --version
GNU indent 2.2.9 (DJGPP port 2004-04-09 (r1))

[1] c:\c\junk>cat \indent.pro
-kr -l66 -i3 -bad -di16 -lc66 -nce -ncs -cbi0 -bbo -pmt -psl -ts1
-cdw

[1] c:\c\junk>indent -h
usage: indent file [-o outfile ] [ options ]
indent file1 file2 ... fileN [ options ]


--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

james of tucson
Guest
 
Posts: n/a
#12: Jan 7 '07

re: Prime Numbers


David T. Ashley wrote:
Quote:
There is a program called "indent"? Sounds useful. Where can I get a copy
for my Linux
apt-get install indent
Quote:
and Windows boxes?
People still run Windows?

rhle.freak
Guest
 
Posts: n/a
#13: Jan 7 '07

re: Prime Numbers




On Jan 6, 11:14 pm, CBFalconer <cbfalco...@yahoo.comwrote:
Quote:
"rhle.freak" wrote:
>
Quote:
I passed your code through indent to make it legible (too big
indentations, line wraps), which worked properly since you avoided
the error of using // comments. Good for you. It makes it easy
for someone to test the code. The result is below, together with
the errors shown up on compilation:
}
...snip....

[1] c:\c\junk>cc junk.c
Quote:
junk.c:10: parse error before '*' token
junk.c:11: warning: return type defaults to `int'
junk.c: In function `create_node':
junk.c:14: `node' undeclared (first use in this function)
junk.c:14: (Each undeclared identifier is reported only once
junk.c:14: for each function it appears in.)
junk.c:14: parse error before ')' token
junk.c:19: warning: return from incompatible pointer type
junk.c: At top level:
junk.c:22: parse error before '*' token
junk.c:23: warning: return type defaults to `int'
junk.c: In function `node_insert':
junk.c:26: warning: assignment from incompatible pointer type
junk.c:31: warning: return from incompatible pointer type
junk.c: In function `main':
junk.c:48: warning: assignment from incompatible pointer type
>
Your biggest error is assuming node is a type. The type name is
"struct node".
Yes ..it should have been struct node,thats how I use it ,but this
compiler(MSVC++) does`nt
show any of these warnings that you got .Maybe i should switch over to
my linux box n gcc
(Though i need to learn how to use them)!

Well regarding my question it was ,that the code showed up wrong *prime
numbers* if i was
initialized to a *large integer*
i.e. i suppose if i used
for(i=15000;i<20000;i++)
in the code , what i was missing is that i am using the generated
prime numbers to actually check
for the remaining cases ,so if i intialized i to something other than 2
,the prime numbers
(in this case before 15000) are not pushed into the stack and erroneous
results are produced.
( the numbers are simply not checked for divisibility by the prime
numbers before 15000)

Quote:
After correcting lines 10, 12, 14, and 22 to the following, it
compiles. You should never cast the return value from malloc.
Every cast is a potential unflagged error and you should know
precisely why you are doing it. After that it appears to run
correctly. You should turn up your compiler warning level.
>
struct node *create_node(void)
{
struct node *z;
>
z = malloc(sizeof(*z));
if (z == NULL) {
printf("Error");
exit(0);
}
return z;
>
}struct node *node_insert(struct node * start, int prime_num)
rhle.freak
Guest
 
Posts: n/a
#14: Jan 7 '07

re: Prime Numbers


/*With one further optimization here is teh corrected code,could you
also
comment on the efficiency of the code,i could not think of any better
way to speed it up
This can check prime numbers within 2 lacs in about 28 seconds on my P4
windows machine*/

/*Generate Prime Numbers*/
#include<stdio.h>
#include<stdlib.h>

struct node{
int data;
struct node *next;
};

struct node* create_node(void)
{
struct node *z;
z=(node*)malloc(sizeof(node));
if(z==NULL)
{
printf("Error");
exit(0);
}
return z;
}

struct node* node_insert(struct node *start,int prime_num)
{
struct node *z;
z=create_node();
z->data=prime_num;
z->next=start;
start=z;

return start;

}

int main(void)
{
int flag;
unsigned /*long long*/ int i;
struct node *start=NULL,*j;
start=node_insert(start,2);/*Just a bit of change*/
printf("%d\n",2);

for(i=3;i<200000;i=i+2) /*and here as well*/
{
flag=0;
for(j=start;j!=NULL;j=j->next)
{
if(i%j->data==0 || i%2==0)
flag=1;
}
if(flag==0)
{
start=node_insert(start,i);
printf("%d\n",i);
}
}
return 0;
}

Richard Heathfield
Guest
 
Posts: n/a
#15: Jan 7 '07

re: Prime Numbers


rhle.freak said:
Quote:
On Jan 6, 11:14 pm, CBFalconer <cbfalco...@yahoo.comwrote:
<snip>
Quote:
Quote:
>Your biggest error is assuming node is a type. The type name is
>"struct node".
>
Yes ..it should have been struct node,thats how I use it ,but this
compiler(MSVC++) does`nt
show any of these warnings that you got .
Then I suggest you invoke it as a C compiler, rather than a C++ compiler.
Try changing your filename's extension to .c - and, while you're at it,
disable Microsoft extensions with /Za and turn your diagnostic level up to
the max with /W4

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Richard Heathfield
Guest
 
Posts: n/a
#16: Jan 7 '07

re: Prime Numbers


rhle.freak said:
Quote:
/*With one further optimization here is teh corrected code,could you
also
comment on the efficiency of the code,
foo.c:18: warning: no previous prototype for `create_node'
foo.c: In function `create_node':
foo.c:20: `node' undeclared (first use in this function)
foo.c:20: (Each undeclared identifier is reported only once
foo.c:20: for each function it appears in.)
foo.c:20: parse error before `)'
foo.c:19: warning: `z' might be used uninitialized in this function
foo.c: At top level:
foo.c:30: warning: no previous prototype for `node_insert'
make: *** [foo.o] Error 1

When it compiles, I'll think about its efficiency. But not before.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Barry
Guest
 
Posts: n/a
#17: Jan 7 '07

re: Prime Numbers



"rhle.freak" <rhle.freak@gmail.comwrote in message
news:1168149073.508334.237410@s34g2000cwa.googlegr oups.com...
Quote:
/*With one further optimization here is teh corrected code,could you
also
comment on the efficiency of the code,i could not think of any better
way to speed it up
This can check prime numbers within 2 lacs in about 28 seconds on my P4
windows machine*/
>
/*Generate Prime Numbers*/
#include<stdio.h>
#include<stdlib.h>
>
struct node{
int data;
struct node *next;
};
>
struct node* create_node(void)
{
struct node *z;
z=(node*)malloc(sizeof(node));
if(z==NULL)
{
printf("Error");
exit(0);
}
return z;
}
>
struct node* node_insert(struct node *start,int prime_num)
{
struct node *z;
z=create_node();
z->data=prime_num;
z->next=start;
start=z;
>
return start;
>
}
>
int main(void)
{
int flag;
unsigned /*long long*/ int i;
struct node *start=NULL,*j;
start=node_insert(start,2);/*Just a bit of change*/
printf("%d\n",2);
>
for(i=3;i<200000;i=i+2) /*and here as well*/
{
flag=0;
for(j=start;j!=NULL;j=j->next)
{
if(i%j->data==0 || i%2==0)
flag=1;
}
if(flag==0)
{
start=node_insert(start,i);
printf("%d\n",i);
}
}
return 0;
}
>
Still missing some "struct"s. The quickest way a can think
of to chop the run time is use a node_append (hint: you
need to keep more than just a list start).

After fixing your code that with one an optimization already
mentioned in this thread and one more taking advantage
of the new ordering of the data if node_append is used
the execution time on my machine goes from 2 minutes
to < 1 second.


Eric Sosman
Guest
 
Posts: n/a
#18: Jan 7 '07

re: Prime Numbers


rhle.freak wrote:
Quote:
/*With one further optimization here is teh corrected code,could you
also
comment on the efficiency of the code,i could not think of any better
way to speed it up
This can check prime numbers within 2 lacs in about 28 seconds on my P4
windows machine*/
[code snipped]
You have overlooked several simple but effective speedups.

1) Once you have discovered that a number is divisible by
some prime (at the point where you set flag=1), there is no
point in continuing to test for divisibility by all the other
primes. The candidate is non-prime, and no amount of further
testing will change the outcome. You can achieve a speedup by
not continuing to test once you've found an exact divisor.

2) With (1) in mind, the order in which you conduct the
divisibility tests becomes significant. Given a "random" odd
integer N, is it more likely to be divisible by 3 or by 31?
If you stop testing as soon as you've found the first divisor,
it makes sense to try the "more likely" divisors first -- in
your case, it makes sense to test the potential prime divisors
in increasing rather than decreasing order. You can achieve a
speedup by putting newly-found large primes at the end rather
than at the beginning of your list.

3) You've modified your main loop so that it only tests
odd candidates, having "granted" yourself 2 as a special-case
prime. Why, they, do you test every candidate for divisibility
by 2 inside the loop? Why, in fact, do you test it again and
again and again? "Is it divisible by 31? Is it divisible by 2?
Is it divisible by 29? Is it divisible by 2? Is it divisible
by 23? Is it divisible by 2? ... Is it divisible by 3? Is it
divisible by 2? Is it divisible by 2 (from the list)? Is it
divisible by 2 (gratuitous)?" You can achieve a speedup by
not making these pointless tests. (In fact, since you never
test even candidates there's no point in having 2 in the list
of divisors at all.)

4) By making a special case of 2 you've cut the pool of
candidates in half. Good start, but you can do better: Make
a special case of 3, and eliminate a third of the remaining
candidates. Considering the pattern of multiples of 2 and 3,
it should be clear that all primes other than 2 and 3 themselves
are of the form 6*k-1 or 6*k+1. This suggests a loop that starts
i at 6 and increments by 6, each time testing the two numbers i-1
and i+1. You can achieve a double-whammy speedup: first by
cutting out another 33% of the candidates without effort, and
second by not bothering to divide by 2 or 3.

5) The idea of (4) can be pursued further by making special
cases of 5 and still larger primes. However, the patterns of
successive multiples get more complex than 6*ką1, and the payoff
shrinks as the eliminated divisors grow larger (e.g., eliminating
31 "by construction" avoids only 3.2% of the work as compared to
the 50% you avoided by eliminating 2).

... and, of course, it would still be nice if you could
produce C code that would actually compile ...

--
Eric Sosman
esosman@acm-dot-org.invalid
Cactus
Guest
 
Posts: n/a
#19: Jan 7 '07

re: Prime Numbers


james of tucson wrote:
Quote:
David T. Ashley wrote:
>
Quote:
There is a program called "indent"? Sounds useful. Where can I get a copy
for my Linux
>
apt-get install indent
>
Quote:
and Windows boxes?
>
People still run Windows?
Yes. Moreover, the number of people who run Windows far exceeds the
number of people who run other operating systems.

james of tucson
Guest
 
Posts: n/a
#20: Jan 7 '07

re: Prime Numbers


Cactus wrote:
Quote:
Quote:
>People still run Windows?
>
Yes. Moreover, the number of people who run Windows far exceeds the
number of people who run other operating systems.
Then they can do their own research.
Barry Schwarz
Guest
 
Posts: n/a
#21: Jan 7 '07

re: Prime Numbers


On 6 Jan 2007 21:51:13 -0800, "rhle.freak" <rhle.freak@gmail.com>
wrote:
Quote:
>/*With one further optimization here is teh corrected code,could you
>also
>comment on the efficiency of the code,i could not think of any better
You have ignored most of the previous comments.
Quote:
>way to speed it up
>This can check prime numbers within 2 lacs in about 28 seconds on my P4
What is lacs?
Quote:
>windows machine*/
>
> /*Generate Prime Numbers*/
>#include<stdio.h>
>#include<stdlib.h>
>
>struct node{
> int data;
> struct node *next;
>};
>
>struct node* create_node(void)
>{
> struct node *z;
> z=(node*)malloc(sizeof(node));
There is no type node* to cast to. In any case, you should never cast
the return from malloc.
Quote:
> if(z==NULL)
> {
> printf("Error");
> exit(0);
> }
> return z;
>}
>
>struct node* node_insert(struct node *start,int prime_num)
>{
> struct node *z;
> z=create_node();
> z->data=prime_num;
> z->next=start;
> start=z;
>
> return start;
>
>}
>
>int main(void)
>{
> int flag;
> unsigned /*long long*/ int i;
> struct node *start=NULL,*j;
> start=node_insert(start,2);/*Just a bit of change*/
This is useless since you never process an even number in the loop.
Quote:
> printf("%d\n",2);
>
> for(i=3;i<200000;i=i+2) /*and here as well*/
> {
> flag=0;
> for(j=start;j!=NULL;j=j->next)
> {
> if(i%j->data==0 || i%2==0)
The second relational expression is still redundant but now also
useless since you never process an even number.
Quote:
> flag=1;
Add a break statement here since you are now certain i is not prime.
No more testing is needed. (Remember to add the braces also.)
Quote:
> }
> if(flag==0)
> {
> start=node_insert(start,i);
> printf("%d\n",i);
> }
> }
> return 0;
>}

Remove del for email
rzed
Guest
 
Posts: n/a
#22: Jan 7 '07

re: Prime Numbers


james of tucson <jmcgill@[go_ahead_and_spam_me].arizona.eduwrote
in news:iX8oh.2792$EH4.2638@newsfe07.phx:
Quote:
Cactus wrote:
>
Quote:
Quote:
>>People still run Windows?
>>
>Yes. Moreover, the number of people who run Windows far
>exceeds the number of people who run other operating systems.
>
Then they can do their own research.
One way to do that research is to ask questions of people who might
know the answer and be willing to provide it. It is not the only way,
true. In the age of Google, it may not be the quickest way. But it is
an acceptable way.

There was a time when people of good will would cooperatively find
solutions to unresolved issues, through such means as establishing
bulletin boards and usenet newsgroups to discuss issues. Sadly, it
does happen that not all questions that arise truly fall within the
purview of a given group's area of concern. At such times, it is
certainly permitted to suggest a more appropriate group to discuss
such issues.

--
rzed
Cactus
Guest
 
Posts: n/a
#23: Jan 7 '07

re: Prime Numbers


james of tucson wrote:
Quote:
Cactus wrote:
>
Quote:
Quote:
People still run Windows?
Yes. Moreover, the number of people who run Windows far exceeds the
number of people who run other operating systems.
>
Then they can do their own research.
They can indeed do their own research, as can anyone who asks questions
of this kind here.

Those interested in C code beautifiers, indenters etc. might take a
look at:

http://universalindent.sourceforge.net/

where there is a cross platform GUI driver for GreatCode, AStyle
(Artistic Styler), GNU Indent, BCPP, ....

I have found that this works well on both Windows and Gnu/Linux and
allows me to choose the beautifier that best suits my own preferences.

loic-dev@gmx.net
Guest
 
Posts: n/a
#24: Jan 7 '07

re: Prime Numbers


Hi Eric,
Quote:
You have overlooked several simple but effective speedups.
>
1) Once you have discovered that a number is divisible by
some prime (at the point where you set flag=1), there is no
point in continuing to test for divisibility by all the other
primes. The candidate is non-prime, and no amount of further
testing will change the outcome. You can achieve a speedup by
not continuing to test once you've found an exact divisor.
>
2) With (1) in mind, the order in which you conduct the
divisibility tests becomes significant. Given a "random" odd
integer N, is it more likely to be divisible by 3 or by 31?
If you stop testing as soon as you've found the first divisor,
it makes sense to try the "more likely" divisors first -- in
your case, it makes sense to test the potential prime divisors
in increasing rather than decreasing order. You can achieve a
speedup by putting newly-found large primes at the end rather
than at the beginning of your list.
>
3) You've modified your main loop so that it only tests
odd candidates, having "granted" yourself 2 as a special-case
prime. Why, they, do you test every candidate for divisibility
by 2 inside the loop? Why, in fact, do you test it again and
again and again? "Is it divisible by 31? Is it divisible by 2?
Is it divisible by 29? Is it divisible by 2? Is it divisible
by 23? Is it divisible by 2? ... Is it divisible by 3? Is it
divisible by 2? Is it divisible by 2 (from the list)? Is it
divisible by 2 (gratuitous)?" You can achieve a speedup by
not making these pointless tests. (In fact, since you never
test even candidates there's no point in having 2 in the list
of divisors at all.)
>
4) By making a special case of 2 you've cut the pool of
candidates in half. Good start, but you can do better: Make
a special case of 3, and eliminate a third of the remaining
candidates. Considering the pattern of multiples of 2 and 3,
it should be clear that all primes other than 2 and 3 themselves
are of the form 6*k-1 or 6*k+1. This suggests a loop that starts
i at 6 and increments by 6, each time testing the two numbers i-1
and i+1. You can achieve a double-whammy speedup: first by
cutting out another 33% of the candidates without effort, and
second by not bothering to divide by 2 or 3.
>
5) The idea of (4) can be pursued further by making special
cases of 5 and still larger primes. However, the patterns of
successive multiples get more complex than 6*ką1, and the payoff
shrinks as the eliminated divisors grow larger (e.g., eliminating
31 "by construction" avoids only 3.2% of the work as compared to
the 50% you avoided by eliminating 2).
Excellent analysis.

Another optimization you can use is that you need to lookup for
divisibility only with the primes p, such that p*p <= n.

Cheers,
Loic.

Richard Heathfield
Guest
 
Posts: n/a
#25: Jan 7 '07

re: Prime Numbers


james of tucson said:
Quote:
David T. Ashley wrote:
>
Quote:
>There is a program called "indent"? Sounds useful. Where can I get a
>copy for my Linux
>
apt-get install indent
>
Quote:
>and Windows boxes?
>
People still run Windows?
We should do all we can to support late adopters who are still using legacy
systems.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
santosh
Guest
 
Posts: n/a
#26: Jan 7 '07

re: Prime Numbers


Richard Heathfield wrote:
Quote:
james of tucson said:
>
Quote:
David T. Ashley wrote:
Quote:
There is a program called "indent"? Sounds useful. Where can I get a
copy for my Linux
apt-get install indent
Quote:
and Windows boxes?
People still run Windows?
>
We should do all we can to support late adopters who are still using legacy
systems.
Is that from an ad for Vista?
:)

Mark McIntyre
Guest
 
Posts: n/a
#27: Jan 7 '07

re: Prime Numbers


On Sat, 6 Jan 2007 15:29:20 -0500, in comp.lang.c , "David T. Ashley"
<dta@e3ft.comwrote:
Quote:
>There is a program called "indent"? Sounds useful. Where can I get a copy
>for my Linux and Windows boxes?
www.google.com + "indent gnu"


--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
David T. Ashley
Guest
 
Posts: n/a
#28: Jan 7 '07

re: Prime Numbers


"Keith Thompson" <kst-u@mib.orgwrote in message
news:lnps9r3lk4.fsf@nuthaus.mib.org...
Quote:
"David T. Ashley" <dta@e3ft.comwrites:
Quote:
>"CBFalconer" <cbfalconer@yahoo.comwrote in message
>news:459FE705.37EA4C0C@yahoo.com...
Quote:
>>I passed your code through indent to make it legible (too big
>>indentations, line wraps), which worked properly since you avoided
>>the error of using // comments. Good for you. It makes it easy
>>for someone to test the code. The result is below, together with
>>the errors shown up on compilation:
>>
>There is a program called "indent"? Sounds useful. Where can I get a
>copy
>for my Linux and Windows boxes?
>
Your Linux box probably already has it. I'm not sure about Windows,
but you can obtain the sources for GNU Indent from
<ftp://ftp.gnu.org/gnu/indent/>.
Thanks for the tip. I did find it as a package (I'm running RHEL), and the
man page looks great.

Coincidentally, I just spent two days prettying up a few thousand lines of
'C', and I'm too lazy to write a parser to automatically arrange code the
way I want. So, this comes in handy.


Richard Heathfield
Guest
 
Posts: n/a
#29: Jan 7 '07

re: Prime Numbers


santosh said:
Quote:
Richard Heathfield wrote:
Quote:
>james of tucson said:
<snip>
Quote:
Quote:
Quote:
People still run Windows?
>>
>We should do all we can to support late adopters who are still using
>legacy systems.
>
Is that from an ad for Vista?
:)
No, it's an ad for SuSE. (Unpaid, I hasten to add.)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
james of tucson
Guest
 
Posts: n/a
#30: Jan 7 '07

re: Prime Numbers


rzed wrote:
Quote:
One way to do that research is to ask questions of people who might
know the answer and be willing to provide it. It is not the only way,
true. In the age of Google, it may not be the quickest way. But it is
an acceptable way.
You're taking this way too seriously. I'm satisfied with "if you had a
linux box you would have discovered indent, among many other things,
years and years ago."

rhle.freak
Guest
 
Posts: n/a
#31: Jan 8 '07

re: Prime Numbers




On Jan 7, 12:35 pm, Richard Heathfield <r...@see.sig.invalidwrote:
Quote:
rhle.freak said:
Quote:
When it compiles, I'll think about its efficiency. But not before.

Guys the code actually does compile and i've tested it a number of
times .I am using vc++ and i am not getting even a single warning
,probably i need to look why it does not compile on gcc !!

Speeding up was what i was looking for and thank to all of you for your
suggestions.I'l try to implement them all.Thanks again

Old Wolf
Guest
 
Posts: n/a
#32: Jan 8 '07

re: Prime Numbers


rhle.freak wrote:
Quote:
On Jan 7, 12:35 pm, Richard Heathfield <r...@see.sig.invalidwrote:
Quote:
rhle.freak said:
>
Quote:
When it compiles, I'll think about its efficiency. But not before.
>
Guys the code actually does compile and i've tested it a number of
times .I am using vc++ and i am not getting even a single warning
,probably i need to look why it does not compile on gcc !!
Why don't you try reading what people are saying to you.
You are compiling with a C++ compiler. You should either:

1) post on comp.lang.c++ instead

or

2) compile with a C compiler.

Note that MSVC can be used either as a C compiler or a C++ compiler;
you are currently using it in C++ mode, for whatever reason.

Richard Heathfield
Guest
 
Posts: n/a
#33: Jan 8 '07

re: Prime Numbers


rhle.freak said:
Quote:
>
>
On Jan 7, 12:35 pm, Richard Heathfield <r...@see.sig.invalidwrote:
Quote:
>rhle.freak said:
>
>
Quote:
>When it compiles, I'll think about its efficiency. But not before.
>
>
Guys the code actually does compile
No, it doesn't.
Quote:
and i've tested it a number of times .I am using vc++ and i am not getting
even a single warning

Check the filename - you should be using a .c extension.
Check the extensions - they should be disabled.
Check the warning level - it should be 4.
Quote:
,probably i need to look why it does not compile on gcc !!
You need to find out why it is not a correct C program. Visual Studio can be
configured to help you do this (see above).
Quote:
Speeding up was what i was looking for
If correctness is not an issue, this works real quick:

int main(void) { return 0; }

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Richard Bos
Guest
 
Posts: n/a
#34: Jan 8 '07

re: Prime Numbers


james of tucson <jmcgill@[go_ahead_and_spam_me].arizona.eduwrote:
Quote:
Cactus wrote:
>
Quote:
Quote:
People still run Windows?
Yes. Moreover, the number of people who run Windows far exceeds the
number of people who run other operating systems.
>
Then they can do their own research.
You do realise that you're a living example of the anti-social behaviour
Linux still has a name for in many circles? Good. Hope you had fun
anti-advertising your favourite virus.

Richard
Dik T. Winter
Guest
 
Posts: n/a
#35: Jan 8 '07

re: Prime Numbers


In article <h392q2lb0r2fieblacmvi3540rbu57js2g@4ax.comBarry Schwarz <schwarzb@doezl.netwrites:
Quote:
On 6 Jan 2007 21:51:13 -0800, "rhle.freak" <rhle.freak@gmail.com>
wrote:
....
Quote:
Quote:
way to speed it up
This can check prime numbers within 2 lacs in about 28 seconds on my P4
>
What is lacs?
I think the Hindi/Urdu lakh: 100,000.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
user923005
Guest
 
Posts: n/a
#36: Jan 8 '07

re: Prime Numbers


/*
Here is Lawrence Kirby's elegant solution to the prime counting
function:
*/
/************************************************** ****************************
* prange.c
*
* L.I.Kirby
*
* 6th September 1992
*
* A couple of algorithms to list and count primes up to reasonably
large
* totals (say 2^32).
*
* Both algorithms make use of rolling totals to generate multiples of
the base
* primes, i.e. the primes < sqrt(upperprime)

************************************************** ***************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>


#define ROLLSIZE 100000
#define SECTIONSIZE 99999
#define SENTINEL ((LARGE_T)-1)

typedef unsigned long long LARGE_T; /* Variables up to upperprime
*/
typedef unsigned long SMALL_T; /* Variables up to sqrt(upperprime) */

typedef int bool;
#define FALSE 0
#define TRUE 1


#define OUTPUT_PRIME(prime) \
do {\
primecount++;\
if (printflag) printf(" %7lu", (unsigned long) prime);\
} while (0)
/* Local functions */

static long prime_heap(LARGE_T, bool);
static void downheap(void);
static long prime_sieve(LARGE_T, LARGE_T, bool);


/* Statics */

static LARGE_T S_roll[ROLLSIZE + 1]; /* Rolling totals */
static SMALL_T S_increm[ROLLSIZE + 1]; /* Increment (the prime number)
*/


/********************************** main()
**********************************
* Decode command options and call prime routine.
*/

int main(int argc, char *argv[])
{
long runcount;
int argind,
rangeind;
char *sptr;
enum {
AL_HEAP, AL_SIEVE
}
algorithm;
LARGE_T lowerprime,
upperprime;
bool printflag;
long primecount;
clock_t start,
end;

upperprime = lowerprime = 0;/* Shut up some compilers */

algorithm = AL_SIEVE;
upperprime = 0L;
printflag = FALSE;

rangeind = 0;
upperprime = 2;
runcount = 1;
for (argind = 1; argind < argc; argind++) {
sptr = argv[argind];
if (*sptr == '-' || *sptr == '/') {
while (*++sptr)
switch (toupper(*sptr)) {
case 'P':
printflag = TRUE;
break;
case 'N':
printflag = FALSE;
break;
case 'S':
algorithm = AL_SIEVE;
break;
case 'H':
algorithm = AL_HEAP;
break;
default:
break;
}
} else if (++rangeind <= 2) {
lowerprime = upperprime;
upperprime = (unsigned long long) atof(sptr);
} else
runcount = atoi(sptr);
}

if (rangeind < 1 || rangeind 3) {
puts("\nUsage: prime2 [-options] [lower] upper");
puts("lower: Search lower bound (default 2)");
puts("upper: Search upper bound (not inclusive)");
puts("Options: P - print primes");
puts(" N - do not print primes (default)");
puts(" H - use heap method");
puts(" S - use sieve method (default)");
exit(EXIT_FAILURE);
}
printf("\nSieve prime search from %I64u to %I64u\n", lowerprime,
upperprime);

start = clock();
do {
if (upperprime <= lowerprime)
primecount = 0;
else if (algorithm == AL_HEAP)
primecount = prime_heap(upperprime, printflag);
else
primecount = prime_sieve(lowerprime, upperprime,
printflag);
}
while (--runcount 0);
end = clock();

printf("\n\nNumber of primes found is %ld\n", primecount);

printf("User time %.2f\n", (double) (end - start) / (double)
CLOCKS_PER_SEC);

return EXIT_SUCCESS;
}


/******************************* prime_heap()
*******************************
* This method maintains a running multiple (the roll) for each base
prime.
* These are maintained in a heap structure so that the smallest roll
value
* i.e. next non-prime is easily determined. Even numbers are skipped.
*
* Although slower than the sieve method, this method uses less memory
and
* still avoids the dreaded divides.
*/


static long prime_heap(
LARGE_T upperprime, /*
Maximum search number */
bool printflag) /* TRUE is
primes should be printed */
{
LARGE_T num; /* The current number being tested for
primeness */

LARGE_T nextnonprime; /* The next smallest number
which has a factor */

long primecount; /* The number of primes found so far */
bool passed_sqrt;/* Set to TRUE once we go beyond
sqrt*upperprime) */

SMALL_T rollhwm; /* High watermark for roll arrays */


printf("\nPrime Heap prime search up to %lu\n", upperprime);

/* Initialise array with sentinels for heap */

for (num = 1; num <= ROLLSIZE; num++)
S_roll[num] = SENTINEL;

/* Deal with the special case of 2 */

primecount = 0;
if (upperprime 2)
OUTPUT_PRIME(2);

/* The main routine */

rollhwm = 1; /* Starting at 1 simplifies the heap
routines */
num = 3;
nextnonprime = 9;
passed_sqrt = FALSE;
for (;;) { /* Here all odd numbers between num and
* nextnonprime are prime */

do {
if (num >= upperprime) /* FINISHED! */
return primecount;

OUTPUT_PRIME(num);

/* If num < sqrt(upperprime) then add to end of heap */

if (!passed_sqrt) {
if (num * num >= upperprime)
passed_sqrt = TRUE;
else {
if (rollhwm >= ROLLSIZE) {
printf("\nROLLSIZE too small. Maximum target is
%lu\n",
num * num);
exit(EXIT_FAILURE);
}
S_roll[rollhwm] = num * num; /* Smallest we
need look
* at -
guaranteed to be
* greater than
any
* current heap
entry */

S_increm[rollhwm] = num + num; /* Skip over
even values */
rollhwm++;
}
}
num += 2;
}
while (num < nextnonprime);

/* We've reached nextnonprime. Search for next prime */

do {
do {
S_roll[1] += S_increm[1]; /* Roll to next odd
multiple */

downheap(); /* Repair heap */
}
while (num == S_roll[1]);
}
while ((num += 2) == S_roll[1]);

nextnonprime = S_roll[1];
}
}


/******************************** downheap()
********************************
* Maintains a heap such that:
* S_roll[n] <= S_roll[2*n] and S_roll[n] < S_roll[2*n+1]
* i.e. S_roll[1] is the smallest element in the heap.
*
* This routine repairs a heap where only the first element is out of
order.
* It expects unused array elements to contain SENTINEL
*/

static void downheap(void)
{
int i,
j;
SMALL_T increm;
LARGE_T roll;

i = 1;
increm = S_increm[1];
roll = S_roll[1];
while ((j = 2 * i) < ROLLSIZE) {
if (S_roll[j] S_roll[j + 1])
j++;

if (roll <= S_roll[j])
break;

S_roll[i] = S_roll[j];
S_increm[i] = S_increm[j];

i = j;
}
S_increm[i] = increm;
S_roll[i] = roll;
}


/****************************** prime_sieve()
*******************************
* This method maintains a running multiple (the roll) for each base
prime
* similar to prime_heap(). However this method uses the multiples to
help
* generate a sieve in sections small enough to fit in memory.
*
* S_sieve[] must be at least sqrt(upperprime) in size but larger
values
* will generally be more efficient. Even numbers are ignored.
*/


static long prime_sieve(
LARGE_T lowerprime, /*
Lower search limit */
LARGE_T upperprime, /*
Upper search limit */
bool printflag)
{ /* TRUE is primes should be printed */
SMALL_T rollind,
sp;
LARGE_T roll,
prime;
SMALL_T sectsize;
LARGE_T sectstart,
sectend;
SMALL_T rollhwm; /* High watermark for roll arrays */
long primecount; /* The number of primes found so far */
bool passed_sqrt;/* Set to TRUE once we go beyond
* sqrt(upperprime) */
LARGE_T l_size = SECTIONSIZE;

static char S_sieve[SECTIONSIZE];
l_size *= l_size;
l_size *= 4;

if (upperprime l_size) {
printf("\nSECTIONSIZE too small. Maximum target is about
%I64u\n",
l_size);
exit(EXIT_FAILURE);
}
/* Deal with the special case of 2 */

primecount = 0;
if (printflag)
putchar('\n');
if (lowerprime <= 2 && upperprime 2)
OUTPUT_PRIME(2);

/* Phase 1 - normal sieve deals with first section and sets up roll
array */

lowerprime /= 2;
rollhwm = 0;
passed_sqrt = FALSE;
sectsize = (upperprime < SECTIONSIZE * 2) ? upperprime / 2 :
SECTIONSIZE;
memset(S_sieve, 0, sectsize);
for (sp = 1; sp < sectsize; sp++) {
if (S_sieve[sp] == 0) {
prime = (LARGE_T) sp *2 + 1;
if (sp >= lowerprime)
OUTPUT_PRIME(prime);

if (!passed_sqrt) {
if (prime * prime >= upperprime) {
if (sectsize <= lowerprime)
break;
passed_sqrt = TRUE;
} else {
if (rollhwm >= ROLLSIZE) {
printf("\nROLLSIZE too small. Maximum target is
%lu\n",
prime * prime);
exit(EXIT_FAILURE);
}
S_increm[rollhwm] = prime;

roll = (prime * prime) / 2;
while (roll < sectsize) {
S_sieve[roll] = 1;
roll += prime;
}
if (roll < lowerprime)
roll = lowerprime + prime - 1 - (lowerprime -
prime / 2 - 1) % prime;

S_roll[rollhwm++] = roll;
}
}
}
}
S_roll[rollhwm] = SENTINEL;

/* Phase 2 - process the large sieve section by section */

upperprime /= 2;
sectstart = (sectsize >= lowerprime) ? sectsize : lowerprime;

rollhwm = 0;
while (S_increm[rollhwm] * S_increm[rollhwm] / 2 < sectstart)
rollhwm++;

sectstart -= sectsize;
while ((sectstart += sectsize) < upperprime) {
sectsize = (upperprime - sectstart < SECTIONSIZE)
? upperprime - sectstart
: SECTIONSIZE;
sectend = sectstart + sectsize;

/* Clear the sieve segment */

memset(S_sieve, 0, sectsize);

/* Fill the sieve segment using the rolling totals */

while (S_roll[rollhwm] < sectend)
rollhwm++;

for (rollind = 0; rollind < rollhwm; rollind++) {
if ((sp = S_roll[rollind] - sectstart) < sectsize) {
prime = S_increm[rollind];

while (sp < sectsize) {
S_sieve[sp] = 1;
sp += prime;
}

S_roll[rollind] = sp + sectstart;
}
}

/* Scan the sieve segment for primes i.e. unmarked entries */

for (sp = 0; sp < sectsize; sp++) {
if (S_sieve[sp] == 0)
OUTPUT_PRIME(2 * (sectstart + sp) + 1);
}
}
return primecount;
}
/*
E:\c\prime>kprime

Usage: prime2 [-options] [lower] upper
lower: Search lower bound (default 2)
upper: Search upper bound (not inclusive)
Options: P - print primes
N - do not print primes (default)
H - use heap method
S - use sieve method (default)

E:\c\prime>kprime 1000000000

Sieve prime search from 2 to 1000000000


Number of primes found is 50847534
User time 3.94
*/

user923005
Guest
 
Posts: n/a
#37: Jan 8 '07

re: Prime Numbers


A very interesting approach:
http://cr.yp.to/primegen.html

Richard Heathfield
Guest
 
Posts: n/a
#38: Jan 8 '07

re: Prime Numbers


user923005 said:
Quote:
A very interesting approach:
http://cr.yp.to/primegen.html
Is that the Bernstein void main horror?

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Keith Thompson
Guest
 
Posts: n/a
#39: Jan 8 '07

re: Prime Numbers


Richard Heathfield <rjh@see.sig.invalidwrites:
Quote:
user923005 said:
>
Quote:
>A very interesting approach:
>http://cr.yp.to/primegen.html
>
Is that the Bernstein void main horror?
I don't know, but it's certainly *a* Bernstein void main horror.

One file even has:

void main(argc,argv)
int argc;
char **argv;
{
[...]
}

I wonder why the author was willing to assume support for void, but
not for prototypes.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
user923005
Guest
 
Posts: n/a
#40: Jan 8 '07

re: Prime Numbers


Keith Thompson wrote:
Quote:
Richard Heathfield <rjh@see.sig.invalidwrites:
Quote:
user923005 said:
Quote:
A very interesting approach:
http://cr.yp.to/primegen.html
Is that the Bernstein void main horror?
>
I don't know, but it's certainly *a* Bernstein void main horror.
>
One file even has:
>
void main(argc,argv)
int argc;
char **argv;
{
[...]
}
>
I wonder why the author was willing to assume support for void, but
not for prototypes.
It has some bugs, but once you fix them it is the fastest prime
counting function I know of.
Quote:
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
mensanator@aol.com
Guest
 
Posts: n/a
#41: Jan 8 '07

re: Prime Numbers



user923005 wrote:
Quote:
Keith Thompson wrote:
Quote:
Richard Heathfield <rjh@see.sig.invalidwrites:
Quote:
user923005 said:
>
>A very interesting approach:
>http://cr.yp.to/primegen.html
>
Is that the Bernstein void main horror?
I don't know, but it's certainly *a* Bernstein void main horror.

One file even has:

void main(argc,argv)
int argc;
char **argv;
{
[...]
}

I wonder why the author was willing to assume support for void, but
not for prototypes.
>
It has some bugs, but once you fix them it is the fastest prime
counting function I know of.
Prime counting and prime generation are two different things.
Quote:
>
Quote:
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
rhle.freak
Guest
 
Posts: n/a
#42: Jan 9 '07

re: Prime Numbers



/*This code finally compiles as a 'c' code and is much faster
(though not super quick..googling around leads to some..) than the
previous ones i posted*/

/*Generate Prime Numbers*/
#include<stdio.h>
#include<stdlib.h>

struct node{
struct node *prev;
int data;
struct node *next;
};

struct node* create_node(void)
{
struct node *z;
z=malloc(sizeof *z);
if(z==NULL)
{
printf("Error");
exit(0);
}
return z;
}

struct node* node_insert(struct node *start,int prime_num)
{
struct node *z;
z=create_node();
z->data=prime_num;
z->next=start;
z->prev=NULL;
start=z;

return start;

}

int main(void)
{
int flag;
unsigned /*long long*/ int i;
struct node *start=NULL,*j,*z,*end=NULL;
z=create_node();
z->data=2;
start=end=z;
z->prev=z->next=NULL;

for(i=3;i<2000000;i=i+2)
{
flag=0;
for(j=end;j!=NULL;j=j->prev)
{
if(i%j->data==0)
{
flag=1;
break;
}
}
if(flag==0)
{
start=node_insert(start,i);
printf("%d\n",i);
}
}
return 0;
}

/*Regarding indentation ..if it is a problem again...please do help
yourselves! ... Please let me
know of any potential errors that i am still missing out on
One more question....if i don't free up the memory allocated at the end
of the program ,what happens to the numbers in the stack ,does this
*callousness* on my part corrupt the memory ?? */

rhle.freak
Guest
 
Posts: n/a
#43: Jan 9 '07

re: Prime Numbers




On Jan 9, 10:33 am, "rhle.freak" <rhle.fr...@gmail.comwrote:
Quote:
/*This code finally compiles as a 'c' code and is much faster
(though not super quick..googling around leads to some..) than the
previous ones i posted*/

n now the errors creep in ! silly me...(sighs)....

rhle.freak
Guest
 
Posts: n/a
#44: Jan 9 '07

re: Prime Numbers




Correcting my silly code ...
node insert function should read as follows:

struct node* node_insert(struct node *start,int prime_num)
{
struct node *z;
z=create_node();
z->data=prime_num;
z->next=start;
z->next->prev=z; /*i missed this*/
z->prev=NULL;
start=z;

return start;

}

This might seem like obsessiveness! please do bear with me ! :-)

user923005
Guest
 
Posts: n/a
#45: Jan 9 '07

re: Prime Numbers


mensanator@aol.com wrote:
Quote:
user923005 wrote:
Quote:
Keith Thompson wrote:
Quote:
Richard Heathfield <rjh@see.sig.invalidwrites:
user923005 said:

A very interesting approach:
http://cr.yp.to/primegen.html

Is that the Bernstein void main horror?
>
I don't know, but it's certainly *a* Bernstein void main horror.
>
One file even has:
>
void main(argc,argv)
int argc;
char **argv;
{
[...]
}
>
I wonder why the author was willing to assume support for void, but
not for prototypes.
It has some bugs, but once you fix them it is the fastest prime
counting function I know of.
>
Prime counting and prime generation are two different things.
Right. This one does both.
http://citeseer.ist.psu.edu/cache/pa...kin99prime.pdf

Richard Heathfield
Guest
 
Posts: n/a
#46: Jan 9 '07

re: Prime Numbers


rhle.freak said:
Quote:
>
/*This code finally compiles as a 'c' code
Yes, it does, at last. Well done. :-)
Quote:
and is much faster
Oh deary deary me. I killed it after two minutes because it was so
mind-numbingly slow, even though I was redirecting output to a file. (It
had got as far as 996263.)

And yet, in theory, it should be quicker than my own prime number generator,
which runs in 0.2 seconds for the same range (up to 2,000,000).

So let's see if we can't speed it up for you, without changing your basic
method (i.e. trial divide by known primes).

But first, let's answer your questions:
Quote:
/*Regarding indentation ..if it is a problem again...please do help
yourselves! ...
If you are having problems with code becoming magically unindented on
Usenet, you can fix that by using spaces instead of tabs in your source
code. Good editors can swap this over for you.
Quote:
Please let me
know of any potential errors that i am still missing out on
One more question....if i don't free up the memory allocated at the end
of the program ,what happens to the numbers in the stack ,does this
*callousness* on my part corrupt the memory ?? */
If you're using a good OS (and even Windows probably counts as a good OS
nowadays), it will reclaim all the memory used by your program when you
quit. Nevertheless, it's good practice to free up the memory correctly, as
programs have a habit of becoming functions. This is because programming
is, in one sense at least, the art of building up big concepts from little
ones. When you turn a program into a function, and then call that function
in a loop, your unimportant, laughably trivial memory leaks can suddenly
become a serious and expensive maintenance headache.

Okay - to the code!

The first thing I'm going to do is set a benchmark. Since I haven't got all
year, I'm going to reduce your top end from 2,000,000 to 300,000.

Redirecting your results to /dev/null, I get your base runtime for 300,000
as 15 seconds on my system. (For 100,000 it was 1.8 seconds, so this is not
a linear relationship by any means.)

Oh, and your program doesn't include 2 amongst the primes.

So let's get our hands dirty.

The first thing to do is get that number list properly abstracted. I made a
trivial change to the program (to divide by smaller numbers first) and the
whole thing broke, so I'd like to make that whole area more robust.

What characteristics do we need in our prime number list? Well, it must be
able to store values in the order they're given. It must be extensible. It
must be iterable (that is, we need to be able to loop through its data
easily). In fact, it would appear that we are best served by an array
rather than a linked list. But a large array can clog up memory quite
easily. So how about a linked list of relatively small arrays? Well, the
possibilities are probably endless, but the implementation is a detail
which we might decide to change later. What really matters is the
interface. So let's design that, in the firm and certain knowledge that all
prime numbers can be represented by an unsigned long int. :-)

We will postulate some type, t_PrimeList, and for now we won't worry about
the underlying details.

We will need to be able to create such a list:

t_PrimeList *PrimeListCreate(void);

And we will need to be able to destroy it:

void PrimeListDestroy(t_PrimeList **);

We should be able to add a number to the list:

int PrimeListAdd(t_PrimeList *, unsigned long new);

PrimeListAdd may reject an entry if it can tell that the entry is not prime,
or if there is insufficient storage for the new entry.

How many numbers are there in the list?

size_t PrimeListCount(t_PrimeList *);

Get the number at a given position:

unsigned long PrimeListRetrieve(t_PrimeList *, size_t);

FOR NOW, we will implement the actual list as a darn great array (because I
have other stuff to do Real Soon Now). Later, if I get time, we'll mod it
into a linked list. This Will Not Affect The Main Program!

Now I can show you main - but beware that this will not yet compile.

int main(void)
{
unsigned long int candidate = 0;
unsigned long n = 0;
unsigned long maxn = (MAX + 5) / 6;
t_PrimeList *primes = PrimeListCreate();
if(primes != NULL)
{
/* two special cases (not really all that special,
but they don't fit our algorithm very well!) */
PrimeListAdd(primes, 2);
PrimeListAdd(primes, 3);

candidate = 5;

for(n = 0; n < maxn; n++)
{
PrimeListAdd(primes, candidate);
candidate += 2;
PrimeListAdd(primes, candidate);
candidate += 4;
}
maxn = PrimeListCount(primes);
for(n = 0; n < maxn; n++)
{
printf("%lu\n", PrimeListRetrieve(primes, n));
}
PrimeListDestroy(&primes);
}

return 0;
}

As you can see, main() betrays not a single hint of the underlying data
structure used by t_PrimeList. Why should it care, after all?

Note, too, that we only test candidates that are either one less than, or
one more than, a multiple of six. That means we have to put 2 and 3 into
our list separately, since they don't fit this pattern.

In case this shortcut isn't clear to you, think of it this way. In any given
list of six consecutive integers starting at a multiple of six:

n * 6 + 0 is even
n * 6 + 1 is neither even nor a multiple of 3
n * 6 + 2 is even
n * 6 + 3 is a multiple of 3
n * 6 + 4 is even
n * 6 + 5 is neither even nor a multiple of 3

Now, n * 6 + 1 and n * 6 + 5 may not be prime, it's true. But apart from the
exceptions already noted above, they are the only ones that *might* be
prime.

Okay, so I implemented all this (be patient - I'll show you the code in a
minute), and (with output redirected to /dev/null to keep the comparison
fair) I got through those 300000 candidates in not 15 seconds but 0.136.

The full two million took 1.26 seconds. Still not quite as fast as my
current generator, but pretty quick nonetheless when compared to your
original version!

If you increase MAX to greater than 2000000, you'll need to increase the
array size too - which is a pain, so our next iteration will deal with
that, if I get time. For now, though, the important thing to communicate is
that you can play with the implementation to your heart's content, and you
*don't have to change main() when you change the implementation!*. Just
leave the interface and semantics alone, and you can do what you like
underneath.

And finally, here's the code:

#include <stdio.h>
#include <stdlib.h>

#define MAX 2000000UL

struct t_PrimeList_
{
unsigned long prime[150000UL]; /* good for a MAX of 2000000UL */
size_t count;
};

typedef struct t_PrimeList_ t_PrimeList;

t_PrimeList *PrimeListCreate(void)
{
t_PrimeList *new = malloc(sizeof *new);
if(new != NULL)
{
memset(new->prime, 0, sizeof new->prime);
new->count = 0;
}
return new;
}
void PrimeListDestroy(t_PrimeList **old)
{
if(old != NULL && *old != NULL)
{
free(*old);
*old = NULL;
}
}

/* this function *only* validates that the new prime candidate is
* not divisible by any candidate already in the list. If you add
* 6 before you add 2 and 3, it will accept 6 as a prime. So just
* add the candidates in order, okay? (The trial division does,
* in any case, assume that they are in order.)
*/
int PrimeListAdd(t_PrimeList *list, unsigned long new)
{
int rc = 1; /* 1 = reject, 0 = accept */
if(list != NULL &&
list->count + 1 < sizeof list->prime / sizeof list->prime[0])
{
size_t n;
rc = 0;
for(n = 0;
rc == 0 && /* not found a prime yet */
n < list->count && /* haven't run out of trial divisors */
list->prime[n] * list->prime[n]
<= new; /* composite still possible */
n++)
{
if(new % list->prime[n] == 0)
{
rc = 1;
}
}
if(0 == rc)
{
list->prime[list->count++] = new;
}
}
return rc;
}

size_t PrimeListCount(t_PrimeList *list)
{
size_t count = 0;
if(list != NULL)
{
count = list->count;
}
return count;
}

unsigned long PrimeListRetrieve(t_PrimeList *list, size_t pos)
{
unsigned long val = 0;
if(list != NULL && list->count pos)
{
val = list->prime[pos];
}
return val;
}

int main(void)
{
unsigned long int candidate = 0;
unsigned long n = 0;
unsigned long maxn = (MAX + 5) / 6;
t_PrimeList *primes = PrimeListCreate();
if(primes != NULL)
{
/* two special cases (not really all that special,
but they don't fit our algorithm very well!) */
PrimeListAdd(primes, 2);
PrimeListAdd(primes, 3);

candidate = 5;

for(n = 0; n < maxn; n++)
{
PrimeListAdd(primes, candidate);
candidate += 2;
PrimeListAdd(primes, candidate);
candidate += 4;
}
maxn = PrimeListCount(primes);
for(n = 0; n < maxn; n++)
{
printf("%lu\n", PrimeListRetrieve(primes, n));
}
PrimeListDestroy(&primes);
}

return 0;
}

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
rhle.freak
Guest
 
Posts: n/a
#47: Jan 9 '07

re: Prime Numbers




On Jan 9, 1:54 pm, Richard Heathfield <r...@see.sig.invalidwrote:
Quote:
rhle.freak said:
>
>
>
Quote:
/*This code finally compiles as a 'c' codeYes, it does, at last. Well done. :-)
>
Quote:
and is much fasterOh deary deary me. I killed it after two minutes because it was so
mind-numbingly slow, even though I was redirecting output to a file. (It
had got as far as 996263.)
On my system i noted a time of 1min n 10 seconds for this range(2
million i.e) :)
which is tons faster than the original one..i had slept through it's
execution :)


Thanks a ton for your fairly detailed analysis.I have not gone into the
exact details of your code as yet(just rushed through the
explanation...hopefully will do that very soon) but i found a runtime
of about 11s for the 2 million mark ...way faster than mine!!

Randy Howard
Guest
 
Posts: n/a
#48: Jan 10 '07

re: Prime Numbers


On Sun, 7 Jan 2007 13:19:43 -0600, David T. Ashley wrote
(in article <F8edncxmbZ5V2jzYnZ2dnUVZ_oCmnZ2d@giganews.com>) :
Quote:
"Keith Thompson" <kst-u@mib.orgwrote in message
news:lnps9r3lk4.fsf@nuthaus.mib.org...
Quote:
>"David T. Ashley" <dta@e3ft.comwrites:
Quote:
>>"CBFalconer" <cbfalconer@yahoo.comwrote in message
>>news:459FE705.37EA4C0C@yahoo.com...
>>>I passed your code through indent to make it legible (too big
>>>indentations, line wraps), which worked properly since you avoided
>>>the error of using // comments. Good for you. It makes it easy
>>>for someone to test the code. The result is below, together with
>>>the errors shown up on compilation:
>>>
>>There is a program called "indent"? Sounds useful. Where can I get a
>>copy
>>for my Linux and Windows boxes?
>>
>Your Linux box probably already has it. I'm not sure about Windows,
>but you can obtain the sources for GNU Indent from
><ftp://ftp.gnu.org/gnu/indent/>.
>
Thanks for the tip. I did find it as a package (I'm running RHEL), and the
man page looks great.
>
Coincidentally, I just spent two days prettying up a few thousand lines of
'C', and I'm too lazy to write a parser to automatically arrange code the
way I want. So, this comes in handy.
It's only been around forever too. :-)


--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw





Randy Howard
Guest
 
Posts: n/a
#49: Jan 10 '07

re: Prime Numbers


On Tue, 9 Jan 2007 02:54:05 -0600, Richard Heathfield wrote
(in article <PIudnVQwEK5wyj7YnZ2dnUVZ8tOmnZ2d@bt.com>):
Quote:
If you are having problems with code becoming magically unindented on
Usenet, you can fix that by using spaces instead of tabs in your source
code. Good editors can swap this over for you.
I know this is warmongering perhaps (not indended, just likely) but I
disagree. By using tabs for indentation, it allows me, or anyone else,
to adjust indentation simply by changing the effective width of the tab
character. That way, regardless of indentation, anyone editing the
code gets the indentation they like, without using indent or some other
tool to modify the source file(s). This can't be done using spaces.
Obviously others disagree, but the logic of it seems pretty clear.

That said, if you use a newsreader which doesn't handle tabs properly
(or at all) then get a better newsreader.



--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw





Randy Howard
Guest
 
Posts: n/a
#50: Jan 10 '07

re: Prime Numbers


On Sat, 6 Jan 2007 22:55:44 -0600, james of tucson wrote
(in article <k3%nh.32669$pm7.20620@newsfe13.phx>):
Quote:
David T. Ashley wrote:
>
Quote:
>There is a program called "indent"? Sounds useful. Where can I get a copy
>for my Linux
>
apt-get install indent
That all depends upon the linux distro actually. Too many cooks
problem.
Quote:
Quote:
>and Windows boxes?
>
People still run Windows?
Sadly, this is apparently the case.



--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw





Closed Thread