我用 Java 快速实现了 SoE 算法(代码在最后)。我的双核 AMD 处理器上的输出是:
分配:31 肉类:10140 上市:10171 筹备结束:10187
正如预期的那样,“肉类”部分消耗了最长时间。
我的一个观察结果是 using
Math.pow(variable, 2)
比(variable * variable)
. 我认为除了函数跳转之外,可能还有其他开销。Math.pow(x, 2) 是否对 2、3 等的幂进行了优化?我问是因为那里有一些用户贡献的 Java 库,它们的乘法算法比 Java 的本机算法快得多。
以下是我的问题:
您可以向“肉类”部分建议哪些算术优化?有什么办法可以完全避免模运算符?
当 start == end 时该功能不起作用。如果我做 sieve(4, 4),返回的数组长度为 1: [4]。我究竟做错了什么?它应该返回 [](基本上是 new int(0))。
您知道哪些与快速数字/数学相关的 Java 库?
谢谢阅读。最后这是我写的代码:不是 GangOfFour/TopCoder 质量,但也不是太可悲(我希望!而且 SO 的代码格式有点……奇怪?):
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Sieve {
public static void main(String[] args) {
/* small test */
int[] primes = sieve(1, 1000000);
}
/**
* returns an array of prime integers
* in the given range
*
* @param start range start
* @param end range end
* @return
*/
private static int[] sieve(int start, int end) {
long startTime = System.currentTimeMillis();
/* some basic range checks */
if(end < start || start < 1 || end < 1) {
throw new ArithmeticException("Messed up input");
}
/* generate ints within range */
int[] naturals = new int[end-start+1];
for (int j = 0; j < end - start + 1; j++) {
naturals[j] = start + j;
}
System.out.println("Allocation: \t" + (System.currentTimeMillis() - startTime));
/* init running prime to start, and increment until
* running prime squared is greater than the end
*/
for (int runningPrime = (start == 1 ? 2: start); end > runningPrime*runningPrime; runningPrime++) {
for (int i = runningPrime; i < naturals.length; i++) {
if(-1 != naturals[i]) {
if(naturals[i] % runningPrime == 0) {
naturals[i] = -1;
}
}
}
}
System.out.println("Meat: \t\t" + (System.currentTimeMillis() - startTime));
if(naturals[0] == 1) {
naturals[0] = -1;
}
/* list primes */
List list = new ArrayList();
for (int i = 0; i < naturals.length; i++) {
if(-1 != naturals[i])
list.add(naturals[i]);
}
System.out.println("Listing: \t" + (System.currentTimeMillis() - startTime));
/* create the return int array */
int[] primes = new int[list.size()];
int k = 0;
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
primes[k++] = ((Integer) iterator.next()).intValue();
}
System.out.println("Preparing end: \t" + (System.currentTimeMillis() - startTime));
return primes;
}
}
感谢所有的反馈。这是下面的固定版本(直到有人设法再次打破它:)
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Sieve {
public static void main(String[] args) {
/* small test */
int[] primes = sieve(2, 5);
System.out.println("Number of primes: " + primes.length);
for (int i : primes) {
System.out.println(i);
}
}
/**
* returns an array of prime integers
* in the given range
*
* @param start range start
* @param end range end
* @return
*/
private static int[] sieve(int start, int end) {
long startTime = System.currentTimeMillis();
/* some basic range checks */
if(end < start || start < 1 || end < 1) {
throw new ArithmeticException("Messed up input");
}
/* generate ints within range */
int[] naturals = new int[(int)Math.floor((end-start+1) / 2) + 1];
int allocator = 0;
for (int j = 0; j < end - start + 1; j++) {
if(!((start + j) % 2 == 0)) {
naturals[allocator++] = start + j;
}
}
System.out.println("Allocation: \t" + (System.currentTimeMillis() - startTime));
/* init running prime to 2, and increment until
* running prime squared is greater than the end
*/
for (int runningPrime = 2; end >= runningPrime*runningPrime; runningPrime++) {
for (int i = 0; i < naturals.length; i++) {
if(-1 != naturals[i]) {
if(naturals[i] != runningPrime && naturals[i] % runningPrime == 0) {
naturals[i] = -1;
}
}
}
}
System.out.println("Meat: \t\t" + (System.currentTimeMillis() - startTime));
if(naturals[0] == 1) {
naturals[0] = -1;
}
/* list primes */
List list = new ArrayList();
for (int i = 0; i < naturals.length; i++) {
if(-1 != naturals[i])
list.add(naturals[i]);
}
System.out.println("Listing: \t" + (System.currentTimeMillis() - startTime));
/* create the return int array */
int size = list.size();
int k = 0;
/* tricky tricky :) */
if(start <= 2) {
size += 1;
k = 1;
}
int[] primes = new int[size];
if(start <= 2) {
primes[0] = 2;
}
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
primes[k++] = ((Integer) iterator.next()).intValue();
}
System.out.println("Preparing end: \t" + (System.currentTimeMillis() - startTime));
return primes;
}
}