SHOW:
|
|
- or go back to the newest paste.
1 | package prime; | |
2 | ||
3 | import java.io.PrintStream; | |
4 | import java.util.ArrayList; | |
5 | import java.util.Arrays; | |
6 | import java.util.Collection; | |
7 | ||
8 | /** | |
9 | * A prime number utility for generating X number of primes, determining whether | |
10 | * a given number is prime, and computing the prime factorization for a number. | |
11 | * | |
12 | * For determining whether a number N is prime, you only need to know all the | |
13 | * primes up to and including sqrt(N). | |
14 | * | |
15 | * @author Philip Diffenderfer | |
16 | * | |
17 | */ | |
18 | public class Prime | |
19 | { | |
20 | ||
21 | public static void main( String[] args ) | |
22 | { | |
23 | - | Prime p = new Prime( 10000000 ); |
23 | + | Prime p = new Prime( 100000 ); |
24 | ||
25 | // Load 100,000 primes into cache | |
26 | long t0 = System.nanoTime(); | |
27 | - | p.initialize( 10000000 ); |
27 | + | p.initialize( 100000 ); |
28 | ||
29 | System.out.println( ( System.nanoTime() - t0 ) * 0.000000001 + " seconds to initialize " + (p.length + 1) + " primes" ); | |
30 | ||
31 | // Last Prime | |
32 | System.out.println( p.primes[p.length] ); | |
33 | ||
34 | // Prime Factors | |
35 | System.out.println( p.factorize( 83475L, new ArrayList<Long>() ) ); | |
36 | ||
37 | // 100 primes | |
38 | p.print( System.out, 100 ); | |
39 | } | |
40 | ||
41 | // The cache of prime numbers | |
42 | private long[] primes; | |
43 | ||
44 | // The index of the last prime number in the cache | |
45 | private int length; | |
46 | ||
47 | /** | |
48 | * Instantiates a new Prime class with a maximum number of primes it can | |
49 | * generate. | |
50 | * | |
51 | * @param primeCountMax | |
52 | * The maximum number of primes this class may be able to store. | |
53 | */ | |
54 | public Prime( int primeCountMax ) | |
55 | { | |
56 | primes = new long[primeCountMax]; | |
57 | primes[0] = 2; | |
58 | primes[1] = 3; | |
59 | primes[2] = 5; | |
60 | length = 2; | |
61 | } | |
62 | ||
63 | /** | |
64 | * Prints out all primes in the prime cache one line at a time into the | |
65 | * PrintStream. | |
66 | * | |
67 | - | public void print( PrintStream out ) |
67 | + | |
68 | * The PrintStream to print the prime cache out to. | |
69 | */ | |
70 | public void print( PrintStream out, int n ) | |
71 | { | |
72 | for (int i = 0; i <= n; i++) | |
73 | { | |
74 | out.println( primes[i] ); | |
75 | } | |
76 | } | |
77 | ||
78 | /** | |
79 | * Determines whether the given number is prime. | |
80 | * | |
81 | * @param n | |
82 | * The number to check for primeness. | |
83 | * @return True if the number is prime, otherwise false. | |
84 | */ | |
85 | public boolean isPrime( long n ) | |
86 | { | |
87 | // Does n exist in the prime cache? | |
88 | if ( isQuickPrimeApplicable( n ) ) | |
89 | { | |
90 | // Perform a quick search for n. | |
91 | return isQuickPrime( n ); | |
92 | } | |
93 | ||
94 | long max = (long) Math.sqrt( n ); | |
95 | ||
96 | // Ensure we have enough primes in the prime cache to determine whether | |
97 | // or not n is a prime. | |
98 | fillPrimes( max ); | |
99 | ||
100 | // If itself is it's only factor, it's a prime. | |
101 | return getFactor( n, max ) == n; | |
102 | } | |
103 | ||
104 | /** | |
105 | * Returns the first prime factor for n, or n if n is prime. | |
106 | * | |
107 | * @param n | |
108 | * The number to find the first prime factor of. | |
109 | * @param nsqrt | |
110 | * The square-root of n. | |
111 | * @return The first prime factor of n, or n if it's prime. | |
112 | */ | |
113 | private long getFactor( long n, long nsqrt ) | |
114 | { | |
115 | for (int i = 0; i <= length; i++) | |
116 | { | |
117 | long p = primes[i]; | |
118 | ||
119 | if ( p > nsqrt ) | |
120 | { | |
121 | return n; | |
122 | } | |
123 | ||
124 | if ( n % p == 0 ) | |
125 | { | |
126 | return p; | |
127 | } | |
128 | } | |
129 | ||
130 | return n; | |
131 | } | |
132 | ||
133 | /** | |
134 | * Ensures the prime cache has all primes up to some number max. | |
135 | * | |
136 | * @param max | |
137 | * The number the prime cache should encompass (have primes <=) | |
138 | */ | |
139 | public void fillPrimes( long max ) | |
140 | { | |
141 | while ( primes[length] < max ) | |
142 | { | |
143 | long p = nextPrime( length ); | |
144 | ||
145 | primes[++length] = p; | |
146 | } | |
147 | } | |
148 | ||
149 | /** | |
150 | * Ensures the prime cache has at least primeCount primes. | |
151 | * | |
152 | * @param primeCount | |
153 | * The minimum number of primes the prime cache should have. | |
154 | */ | |
155 | public void initialize( int primeCount ) | |
156 | { | |
157 | --primeCount; | |
158 | ||
159 | while ( length < primeCount ) | |
160 | { | |
161 | long p = nextPrime( length ); | |
162 | ||
163 | primes[++length] = p; | |
164 | } | |
165 | } | |
166 | ||
167 | /** | |
168 | * Computes the next prime in the sequence of all primes based on the prime | |
169 | * at the given index in the prime cache. | |
170 | * | |
171 | * @param n | |
172 | * The index of a prime in the prime cache, the prime this method | |
173 | * returns will be the next prime in the sequence. | |
174 | * @return The next prime in the sequence of primes. | |
175 | - | long x = primes[n] + jump( n ); |
175 | + | |
176 | public long nextPrime( int n ) | |
177 | { | |
178 | long x = primes[n] + 2; | |
179 | - | x += jump( ++n ); |
179 | + | |
180 | while ( getFactor( x, (long) Math.sqrt( x ) ) != x ) | |
181 | { | |
182 | x += 2; | |
183 | } | |
184 | ||
185 | return x; | |
186 | } | |
187 | ||
188 | /** | |
189 | * A number is a quick prime if it exists in the currently generated cache | |
190 | * of primes. This can efficiently be determined with a binary search. | |
191 | * | |
192 | * @param n | |
193 | * The prime to check. | |
194 | * @return True if the given number exists in the prime cache. | |
195 | */ | |
196 | public boolean isQuickPrime( long n ) | |
197 | { | |
198 | return Arrays.binarySearch( primes, 0, length + 1, n ) >= 0; | |
199 | } | |
200 | ||
201 | /** | |
202 | * A number is quick prime applicable if there exists a prime in the cache | |
203 | * that is larger than the provided number. This implies a search can be | |
204 | * done in the array to determine if the provided number is a prime. | |
205 | * | |
206 | * @param n | |
207 | * The number to check for quick prime applicability. | |
208 | * @return True if the number exists on the prime cache, otherwise false. | |
209 | */ | |
210 | public boolean isQuickPrimeApplicable( long n ) | |
211 | { | |
212 | return n <= primes[length]; | |
213 | - | * Given the index of a prime, return the jump (either 2 or 4) to use to |
213 | + | |
214 | - | * approximate the next prime. The first 3 primes are excluded from this |
214 | + | |
215 | - | * rule. |
215 | + | |
216 | * Adds all prime factors of n to the given collection of numbers. | |
217 | - | * @param x |
217 | + | |
218 | - | * The index of the prime. |
218 | + | |
219 | - | * @return The amount to jump to the next possible prime. |
219 | + | |
220 | * @param primeFactors | |
221 | - | private int jump( int x ) |
221 | + | |
222 | * @return The collection given. | |
223 | - | return ( 1 << ( ( x & 1 ) + 1 ) ); |
223 | + | |
224 | public <D extends Collection<Long>> D factorize( long n, D primeFactors ) | |
225 | { | |
226 | if ( isQuickPrimeApplicable( n ) && isQuickPrime( n ) ) | |
227 | { | |
228 | return primeFactors; | |
229 | } | |
230 | ||
231 | long max = (long) Math.sqrt( n ); | |
232 | ||
233 | fillPrimes( max ); | |
234 | ||
235 | while ( n != 1 ) | |
236 | { | |
237 | long f = getFactor( n, max ); | |
238 | ||
239 | primeFactors.add( f ); | |
240 | ||
241 | n /= f; | |
242 | ||
243 | max = (long) Math.sqrt( n ); | |
244 | } | |
245 | ||
246 | return primeFactors; | |
247 | } | |
248 | ||
249 | } |