package utils; /** * This class Generates prime numbers up to a user specified * maximum. The algorithm used is the Sieve of Eratosthenes. * Given an array of integers starting at 2: * Find the first uncrossed integer, and cross out all its * multiples. Repeat until there are no more multiples * in the array. */ public class PrimesGenerator { private static boolean[] crossedOut; private static int[] result; public static int[] generatePrimes(int maxValue) { if (maxValue < 2) { return new int[0]; } else { uncrossIntegersUpTo(maxValue); crossOutMultiples(); putUncrossedIntegerIntoResult(); return result; } } private static void putUncrossedIntegerIntoResult() { result = new int[numberOfUnCrossedIntegers()]; for (int j = 0, i = 2; i < crossedOut.length; i++) { if (notCrossed(i)) { result[j++] = i; } } } private static int numberOfUnCrossedIntegers() { int count = 0; for (int i = 2; i < crossedOut.length; i++) { if (notCrossed(i)) { count++; } } return count; } private static void crossOutMultiples() { int limit = determineIterationLimit(); for (int i = 2; i < limit; i++) { if (notCrossed(i)) { crossOutMultiplesOf(i); } } } private static int determineIterationLimit() { // We cross out all multiples of p; where p is prime. // Thus, all crossed out multiples have p and q for // factors. If p > sqrt of the size of the array, then // q will never be greater than 1. Thus p is the // largest prime factor in the array, and is also // the iteration limit. double iterationLimit = Math.sqrt(crossedOut.length); return (int) iterationLimit; } private static void crossOutMultiplesOf(int i) { for (int multiple = 2*i; multiple < crossedOut.length; multiple+=i) { crossedOut[multiple] = true; } } private static boolean notCrossed(int i) { return crossedOut[i] == false; } private static void uncrossIntegersUpTo(int maxValue) { crossedOut = new boolean[maxValue + 1]; for (int i = 2; i < crossedOut.length; i++) { crossedOut[i] = false; } } }
package test; import junit.framework.*; import utils.PrimesGenerator; public class TestPrimesGenerator extends TestCase { public static void main(String[] args) { junit.swingui.TestRunner.main( new String[]{"test.TestPrimesGenerator"} ); } public TestPrimesGenerator(String name) { super(name); } public void testPrimes() { int[] nullArray = PrimesGenerator.generatePrimes(0); assertEquals(nullArray.length, 0); int[] minArray = PrimesGenerator.generatePrimes(2); assertEquals(minArray.length, 1); assertEquals(minArray[0], 2); int[] threeArray = PrimesGenerator.generatePrimes(3); assertEquals(threeArray.length, 2); assertEquals(threeArray[0], 2); assertEquals(threeArray[1], 3); int[] centArray = PrimesGenerator.generatePrimes(100); assertEquals(centArray.length, 25); assertEquals(centArray[24], 97); } }
参考:《敏捷软件开发:原则、模式与实践》