如何有效地实现Eratosphenes方法生成素数?

时间:2014-11-18 11:58:23

标签: java

我在代码中使用以下组件:

  • 字节数组,每个位表示对应的数字是否为素数(0)或不是(1)
  • Filtering.filter()
  • 的递归

我想确定这些部件是否使其效率更高或实际上减慢速度。任何其他建议也表示赞赏。

代码:

import java.lang.Math;
import java.util.*;

class Container{
    public final byte[] binary_array;
    private final int bit_length;

    public Container(int nominal_bit_length){
            int byte_length = (int)Math.ceil(nominal_bit_length / 8.0);
            this.binary_array = new byte[byte_length];
            this.bit_length = 8 * byte_length;
    }

    private String toBinaryString(int index){//convert into a binary string the byte value on which the bit number refered by the index exists
            int byte_index = index / 8;
            //System.out.println(index);
            String str = Integer.toBinaryString(this.binary_array[byte_index]);
            String formatted = ("00000000" + str).substring(str.length());
            return formatted;
    }

    public char get(int index){
            String str = this.toBinaryString(index);
            return str.charAt(index % 8);//
    }

    public char set(int index, char value){
            StringBuilder str = new StringBuilder(this.toBinaryString(index));
            char temp = str.charAt(index % 8);//
            str.setCharAt(index % 8, value);//
            int byte_index = index / 8;
            this.binary_array[byte_index] = (byte)Integer.parseUnsignedInt(str.toString(), 2);
            return temp;
    }

    public int length(){
            return this.bit_length;
    }

    public static Container preset(){
            Container c = new Container(8);
            c.set(1-1, '1');
            c.set(4-1, '1');
            c.set(6-1, '1');
            c.set(8-1, '1');
            return c;
    }



}

class Screener{



    private static void filterMultiplesOf(int num, Container container){
            if (num == 1){
             return;
            }
            int i = 2;
            while ((i * num - 1) < container.length()){
                    container.set(i * num - 1, '1');
                    i++;
            }
    }

    public static void filter(Container c){
            int num = c.length();
            if (num <= 8){
                    c = Container.preset();
            } else{
                    Container base = new Container((int)Math.floor(Math.sqrt(num)));
                    filter(base);
                    for (int i = 0; i < base.length(); i++){
                            if (base.get(i) == '0'){
                                    filterMultiplesOf(i+1, c);
                            }
                    }
            }

    }
}

public class Prime2{
    public static void main(String[] args){
            Scanner reader = new Scanner(System.in);
            int num = reader.nextInt();
            Container c = new Container(num);
            Screener.filter(c);


            for (int i = 1; i < c.length(); i++){
                    if (c.get(i) == '0'){
                            System.out.print((i + 1) + " ");
                    } 
            }   
    }

}

于12-03-2014编辑: 这段代码怎么样?

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;


public class PrimeGenerator {



    public static Set<Integer> prime(int num){
            if (num <= 2){
                    Set<Integer> foo = new HashSet<>();
                    foo.add(2);
                    return foo;
            }
            IntStream stream = IntStream.rangeClosed(1, num);
            Set<Integer> base = prime((int)Math.ceil(Math.sqrt(num)));
            IntStream multiples = base.stream().flatMapToInt((factor) -> (IntStream.rangeClosed(2, (int)Math.floorDiv(num, factor)).map(n -> n * factor)));
            Set<Integer> primeset = stream.collect(HashSet::new, HashSet::add, HashSet::addAll);
            Set<Integer> nonprimeset = multiples.collect(HashSet::new, HashSet::add, HashSet::addAll);
            primeset.removeAll(nonprimeset);
            primeset.remove(1);
            return primeset;
    }

    public static void main(String[] args) {
            // TODO code application logic here
            prime(100000).stream().map(num -> num + "  ").forEach(System.out::print);
    }

}

以及:

import java.lang.Math;
import java.util.*;

/**
* Variation of BitSet which does NOT interpret the highest bit synonymous with
* its length.
*
* @author casper.bang@gmail.com
*/
class FixedBitSet extends BitSet{

    int fixedLength;

    public FixedBitSet(int fixedLength){
        super(fixedLength);
        this.fixedLength = fixedLength;
}

    @Override
    public int length() {
        return fixedLength;
    }
}


class Screener{

    private static FixedBitSet preset;

    static{
            preset = new FixedBitSet(4);
            preset.set(1-1, true);
            preset.set(4-1, true);
    }

    private static void filterMultiplesOf(int num, FixedBitSet bitset){
            //System.out.println("--------");

            if (num == 1){
                    return;
            }

            int i = 2;
            while ((i * num - 1) < bitset.length()){
                    bitset.set(i * num - 1, true);
                    i++;
            }
    }

    public static void filter(FixedBitSet bitset){
            //System.out.println("--------");

            int num = bitset.length();
            if (num <= 4){
                    //System.out.println("--------");
                    bitset = preset;
            } else{
                    FixedBitSet base = new FixedBitSet((int)Math.floor(Math.sqrt(num)));
                    filter(base);
                    for (int i = 0; i < base.length(); i++){
                            if(!base.get(i)){
                                    filterMultiplesOf(i + 1, bitset);
                            }
                    }
            }

    }
}

public class Prime3{

    public static void main(String[] args){
            Scanner reader = new Scanner(System.in);
            int num = reader.nextInt();
            FixedBitSet bs = new FixedBitSet(num);
//                System.out.println(bs.length());
            Screener.filter(bs);

            for (int i = 1; i < bs.length(); i++){
                    if(!bs.get(i)){
                            System.out.print((i + 1) + " ");
                    }
            }
    }
}

1 个答案:

答案 0 :(得分:1)

对字节数组的“高效”使用对代码的不良性能无关紧要,代码使用字符串构建来实现获取和设置。

而是编写使用低级位操作运算符(例如~&|)的代码来实现getset

如果你不满意,那么考虑使用BitSet,这是一个JDK提供的类,用于相同的目的。

如果您想了解它是如何完成的,那么只需打开BitSet的源代码即可。