Fun with Prime Numbers
Steve Litt writes "Fun
With Prime Numbers contains a series of prime number finding algorithms starting with the most brute force imaginable, and working up to a paged algorithm capable of finding the first 1,716,050,469 primes in an hour and a half on a commodity machine. There are faster algorithms on the net, but these algorithms are within the reach of mere mortals and are fully explained."
This article will be a prime target for bad jokes.
Mom says my
I got a 404...
"I'll have a Guinness, no wait, make that a Coors Light" -Grad student I work with, who shall remain anonymous...
Why not just save primes on a disk instead of recalculating them all the time?
I understand that number sequences like Fibonacci manifest themselves in Nature and others like pi provide a fairly decent random number generation method. However, aside from the interesting property that they can't be divided by anything other than themselves and 1, I do not 'get' what is interesting or useful about prime numbers.
But then again, I haven't studied mathematics to any great extent beyond the multi-var calc and linear algebra back in high school. That was such a long time ago. Any math Geniuses out there want to clue is in on why primes are interesting?
So the macros knock the time down from 4.49 to 4.15 seconds -- less than a 10% reduction. In my opinion, that's not enough benefit to give up the robustness and typechecking of functions.
I never thought that I'd see a C programmer type something like that.
BTW, the first bazillion prime numbers HAVE been calculated, so for those /.'ers with spare CPU cycles, consider something perhaps more worthwhile such as Folding@HOME
Hulk SMASH Celiac Disease
Read Penn Jillette's great explanation for details.
Vino, gyno, and techno -Bruce Sterling
A very fast segmented sieve (to find primes in an arbitrary range) can be found here, by Tomás Oliveira e Silva.
Of tangential interest is his Goldbach conjecture verification project. You can download his client and contribute to the project. He's shooting for 10^18...
There is a command in many unices and Linux called factor.
If you want to be a true geek you can try it on your friends phone numbers and find out if it is a prime.
Then, the next time you talk, inform them that their phone number is a prime, or tell them of their phone numbers prime factorization, and enjoy watching them think that you are a super geek and a super genius.
For even better effect, pretend to count in your head before you tell them this.
The Internet is full. Go Away!!!
Find out more on the Nth Prime Page.
From the article:
... * 65537 + 2 = 2 * (3 * ... * 65537 + 1) ... * 65537 + 3 = 3 * (2* 4 * ... * 65537 + 1)
...
... * 65536 * 65537 + 65537 = 65537(65536!+1)
..., 65537! + 65537 are all nonprime (the first is divisible by 2, the second by 3, the thrid by 4 etc). Since we also know that there are infinitely many primes, there must be a prime greater than 65537! + 65537. The biggest prime less than 65537! + 2 and the least prime bigger than 65537! + 65537 are consecutive primes which are at least 65536 apart.
..., 6! + 5} ={722, 723, 724, 725, 726} are all nonprime, but also 24, 25, 26, 27, 28 are 5 consecutive nonprime numbers.
who can be sure that there aren't two consecutive primes somewhere that are more than 65536 apart
Let's recall elementary number theory:
65537! + 2 = 2 * 3 *
65537! + 3 = 2 * 3 *
65537! + 65537 = 2* 3 *
So the 65536 consecutive numbers 65537! +2 ,
Of course, 65537! is a massive number, which is unlikely to crop up in these calculations. There may be other sufficiently large gaps between primes among smaller numbers.
Consider, for instance, the method above applied with 5 in the place of 65536. We see that {6! +2,
For where we can expect large 'prime-free' gaps, I'll defer to any number theorist.
If you're interested in running a distributed.net-like application with the chance to make some money using your CPU cycles to help find prime numbers, have a look at here. They give some good information about what prime numbers are, and what they're good for.
BeauHD. Worst editor since kdawson.
How about when you're on the vintage mainframe level in Tron 2.0, ask some random program to calculate the seventh even prime number. When he segfaults, you get access to the directory containing Tron Legacy. Just don't ask yourself that question...
Have a look here for a pretty tight upper bound on the number of primes up to a given number. Using an array, instead of a linked list, would probably lead to a small speed improvement on his code.
He could also use an std::vector from C++. As far as I can tell it's pretty easy to resize.
Join the NFSNET. Our prime goal is making little numbers out of big ones. http://www.nfsnet.org/
encryption.
"It is not how things are in the world that is mystical, but that it exists." -Ludwig Wittgenstein
The Prime Number Shitting Bear. Watching a console window spit out prime numbers might do it for the geeks, but everyone can loves the prime number shitting bear.
For those who scoff at this kind of stuff, we have to keep in mind that it's this sort of tinkering that results in some of the most amazingly useful and interesting stuff later.
I have one lament, which is that his code formatting (indenting) got munged, making it really hard to read the code. I'm really tired, so I just couldn't manage to read through all the C code. I hope he fixes the page so that I can read it more easily later.
As mentioned, DJB's primegen is much faster. Even his Sieve of Eratosthenes implementation will do the primes up to a billion in 1.38 seconds on a 2.4 GHz P4, which is roughly 100x faster than this guy's "all primes below 100 million in less than 13 seconds" (although he doesn't specify on what machine). There's no reason to be using huge memory "pages," you can sieve up to N with any size interval you want (like say, the size of your L1 d-cache) using only Sqrt(N) memory for the primes up to Sqrt(N).
...and I'm going to list a few improvements here that I think the author missed.
In one of the early programs, the author had the idea of skipping all even numbers, which are of course divisible by 2. In the next program he found out how he could skip numbers divisible by 3. One can make a systematic method out of that -- in the literature it's known as adding a wheel to the sieve of Erathostenes. Thing is, he implemented the sieve of Erathostenes foregoing this improvement he had implemented earlier. This leads to a big improvement: when using a wheel with the first four primes 2,3,5,7, there are only 48 residue classes out of 210 = 2*3*5*7 possible that are not divisible by any of these four primes. In practice this means that, for each 210 numbers you'd consider, the sieve would only need be applied in 48 of them. That's a gain of 4.375. One can make a gain of nearly 5 using a wheel of the first five primes, but it begins to get complicated.
Another improvement would be to make the program cache-friendly. He sort of did this, down one level of the memory hierarchy, by paging the data to disk -- now he only needed to realize that, just as memory is much faster than disk, cache memory is faster than main memory. I've developed a sieve employing this optimization and it pays off indeed. This is considered a basic technique in the realm of high-performance computing. (The NFSNET, see my sig, uses a sieve including this and other optimizations, for instance).
I might get flamed for this, but he should consider assembly programming. There aren't many applications where assembly will pay off so handsomely as this one, and the `core' of the sieve is very small, so only a few lines of assembly are needed. Vector integer instructions, such as MMX and the integer instructions of SSE2, can be employed to very good advantage here. My sieve program also included this, and it gives a real nice boost -- and only about 25 lines of assembly were used, the rest was C.
Lastly there's the issue of representing the output. He stored the primes on disk by writing their values. A little compression can be realized in this representation: for instance he's printing out the primes in decimal, while hexadecimal would be more space-efficient. And instead of printing out the ASCII characters from 0 to 9, A to F, he could use a binary representation and read them through an hex dump -- that saves half the space, as a byte is used to store two hexadecimal digits instead of one.
A perfectly good representation that could save a lot of space (8 times, to be precise) would be a bitmap, which he used on some of his programs. That's where you represent primality or lack of it by setting and clearing bits of an integer. It's pretty easy to determine a prime from a bitmap value, so this representation is just as good as the previous one. One could also use the wheel idea I explained before to save even more space: a concrete example would be that for each block of 210 numbers, one needs only bitmaps for 48 of them, as the rest are divisible by the first four primes. In this example a savings of 4.375 would be realized. Of course, all these ideas would require special readers programs, instead of just opening up the files in a text editor -- a small price to pay for such a large space savings.
But in case only sequential reading of the primes is desired, there is an even more efficient representation: just write out the prime gaps, i.e. the difference between consecutive primes. One bit can be saved by realizing that, other than 3 - 2, all prime gaps are even, so one can just store the prime gap divided by two. One could really nitpick and point out that 0 is an impossible prime gap, so one could subtract two from all gaps, but this gain is too small to be worth the hassle. According to Thomas Nicely (incidentally the guy who discovered the bug on the Pentium FPU during his studies on computational number theory), one could store the prime gaps of all
Join the NFSNET. Our prime goal is making little numbers out of big ones. http://www.nfsnet.org/
I'd venture to say I know what I'm talking about. One can't publish a paper about large-scale distributed primality proofs without knowing these basics. Here's a sample of my work. Now don't get me wrong, I'm not trying to sound like a smart-ass, but I'm not going to let someone question my knowledge in this field (which I have studied for years) and remain quiet.
Now it seems people here are not familiar with the terminology associated with Mersennes, so I'll give a crash course.
A Mersenne number M_n is of the form 2^n - 1. If 2^n - 1 is prime, then M_n is a Mersenne prime. If 2^n - 1 is composite, then M_n is a Mersenne composite. The integer n in this expression is called the exponent. When I talk about `exponents of Mersenne composites', I'm refering to some prime n for which M_n = 2^n - 1 is composite.
Now if 2^n - 1 is prime, then n must be prime, but the converse is not always true, the smallest counterexample being 2^11 - 1 = 2047 = 23*89. Turns out that for prime exponents n = 24,036,583, only in 41 cases is 2^n - 1 actually prime. A list of these cases can be found here. For the other 1,509,222 prime values of n = 24,036,583, 2^n - 1 is composite. This translates to a compositeness ratio of 99.9973%.
I hope everything is clearer now.
Join the NFSNET. Our prime goal is making little numbers out of big ones. http://www.nfsnet.org/
How to prove that all odd numbers are prime? Well, this problem has different solutions whether you are a:
usage: prime [-nV] [--quiet] [--silent] [--version] [-e script] --catenate --concatenate | c --create | d --diff --compare | r --append | t --list | u --update | x -extract --get [ --atime-preserve ] [ -b, --block-size N ] [ -B, --read-full-blocks ] [ -C, --directory DIR ] [--checkpoint ] [ -f, --file [HOSTNAME:]F ] [ --force-local ] [ -F, --info-script F --new-volume-script F ] [-G, --incremental ] [ -g, --listed-incremental F ] [ -h, --dereference ] [ -i, --ignore-zeros ] [ --ignore-failed-read ] [ -k, --keep-old-files ] [ -K, --starting-file F ] [ -l, --one-file-system ] [ -L, --tape-length N ] [ -m, --modification-time ] [ -M, --multi-volume ] [ -N, --after-date DATE, --newer DATE ] [ -o, --old-archive, --portability ] [ -O, --to-stdout ] [ -p, --same-permissions, --preserve-permissions ] [ -P, --absolute-paths ] [ --preserve ] [ -R, --record-number ] [ [-f script-file] [--expression=script] [--file=script-file] [file...]
prime: you must specify exactly one of the r, c, t, x, or d options
For more information, type "prime --help''
Segmentation fault, Core dumped.
Non-Linux Penguins ?
It consists of a bunch of proofs that there is no largest prime - the list of proofs is entitled "15 good reasons why Pure Mathematics is not taught to first year students." My favourites are:
Proof by example:
"Let x be the largest prime. Then x=91 but 91+6=97 which is prime. Therefore 91 cannot be the largest prime number. Therefore there is no largest prime."
Proof by intuition:
"Prime numbers are integers that can be divided by themselves only; prime numbers are odd with the exception of 2. By intuition as n->infinity, there will always be an odd number cannot be divided by another number besides itself."
Proof by experimental data:
"Suppose n is the highest prime. Then 2n-1 is also prime. But 2n-1>n so there is no highest prime. (Check: 2*2-1=3, 2*3-1=5, 2*5-1=11, 2*11-1=23, so true.)"
But the greatest of them all:
Proof by having no idea what a prime is:
"Say the largest prime is x, then 2x is also a prime since the statement is true for all natural numbers."
Go to http://www.ms.unimelb.edu.au/~paradox/archive/ for the magazine, these proofs appeared in issue 2 of 2002.