Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 循环i++;vs i+=2._Java - Fatal编程技术网

Java 循环i++;vs i+=2.

Java 循环i++;vs i+=2.,java,Java,我一直在尝试一种高效的算法来寻找素数,作为我尝试的一部分,我一直在使用下面的代码。我有一个想法,通过改变I+=2的激励来加速循环,但实际上,这个改变似乎使我的程序的运行时间增加了2秒。有谁能解释为什么会发生这种情况,因为循环似乎需要完成一半的工作才能完成 for(int i = answers.get(answers.size()-1)+2;i<n;i++) { int bit = i%64; int currentInt = i/64;

我一直在尝试一种高效的算法来寻找素数,作为我尝试的一部分,我一直在使用下面的代码。我有一个想法,通过改变I+=2的激励来加速循环,但实际上,这个改变似乎使我的程序的运行时间增加了2秒。有谁能解释为什么会发生这种情况,因为循环似乎需要完成一半的工作才能完成

for(int i = answers.get(answers.size()-1)+2;i<n;i++) {
        int bit = i%64;
        int currentInt = i/64;

        int isPrime = (primes[currentInt] >> bit) & 1;
        if(isPrime == 1) {answers.add(i);}
    }
for(inti=answers.get(answers.size()-1)+2;i>bit)&1;
如果(isPrime==1){answers.add(i);}
}
完整代码如下:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

public class Primes15 {
  static Long start;

  public static IntStream stream() {
    int numbers = 15350808;
    int n = 982451712;
    List<Integer> answers = new ArrayList<>();
    long[] inverseShifts = new long[64];
    long temp = 1;

    for(int i = 0; i < inverseShifts.length; i++) {
      inverseShifts[i] = temp ^ -1;
      temp = temp << 1;
    }

    long[] primes = new long[numbers+1];
    primes[0] = -6148914691370734930L;
    for(int i = 1;i<primes.length; i++) {
      primes[i] = -6148914691370734934L;
    }

    System.out.println("Setup taken " + (System.currentTimeMillis() - start) + "  millis");
    start = System.currentTimeMillis();

    for(int p =3; p*p <=n; p+=2) {
      int bit = p%64;
      int currentInt = p/64;
      long isPrime = (primes[currentInt] >> bit) & 1;
      if(isPrime == 1) {
        answers.add(p);
        int cPrimeSquared = p*p;
        int change = (p==2)? p : p+p;
        for(int i = cPrimeSquared; i <= n; i += change) {
          int innerBit = i % 64;
          int innerInt = i /64;
          isPrime = (primes[innerInt] >> innerBit) & 1;
          if(isPrime == 1) {
            primes[innerInt] = primes[innerInt] & inverseShifts[innerBit];
          }
        }
      }
      System.out.println("finder took " + (System.currentTimeMillis() - start) + "  ms");
      start = System.currentTimeMillis();
      for(int i = answers.get(answers.size()-1)+2; i<n; i++) {
        int bit = i%64;
        int currentInt = i/64;
        long isPrime = (primes[currentInt] >> bit) & 1;
        if(isPrime == 1) {answers.add(i);}
      }
      System.out.println("search took " + (System.currentTimeMillis() - start) + "  ms");
      start = System.currentTimeMillis();

      return answers.stream().mapToInt(i->i);
    }

  public static void main(String[] args) {
    start = System.currentTimeMillis();
    stream();
    Long finish = System.currentTimeMillis();
    System.out.println("Time taken " + (finish - start) + "  millis");
  }
}
import java.util.ArrayList;
导入java.util.List;
导入java.util.stream.IntStream;
公共类素数15{
静态长启动;
公共静态IntStream(){
整数=15350808;
int n=982451712;
列表答案=新建ArrayList();
long[]inverseShifts=新长[64];
长期温度=1;
对于(int i=0;ibit)&1;
如果(isPrime==1){answers.add(i);}
}
System.out.println(“搜索时间”+(System.currentTimeMillis()-start)+“ms”);
start=System.currentTimeMillis();
返回answers.stream().mapToInt(i->i);
}
公共静态void main(字符串[]args){
start=System.currentTimeMillis();
流();
长时间完成=System.currentTimeMillis();
System.out.println(“所用时间”+(完成-开始)+“毫秒”);
}
}

我用JMH做了一些测试-因为整个代码都丢失了,而且仍然很难阅读,所以我使用了一个简化的、朴素的版本(不适用于查找素数,但具有类似的计算IMHO):

也就是说,按每个操作的纳秒排序:

预期的种类:增加2会快2倍;令人惊讶的是,
i+=1
i++
慢了一点-我假设编译器为这两种代码创建相同的操作码

第一次联系JMH,不确定我是否100%
正确,但必须测试它[:-)

你能把你的
答案
素数
移位
声明包括在内吗?我实际上已经改变了,那一行将被更新。答案被声明为空,但它已经有许多素数被添加到31337。素数是一个长数组,此时其中有15350809个数字。移位是一个由64个长数字组成的数组,第一个是63 0,后面是1,每个数字都按位置移位(1、10、100等)。给定的代码甚至不应该编译(假设
primes
确实是
long[]
)-缺少int的转换;
shift
根本不被使用(发布/编辑的代码);我们不知道花了多少时间;请在问题中发布并添加其他信息,而不是(仅)作为评论。我认为您应该对其进行分析,甚至不清楚问题是否存在于循环中。如果您希望我们阅读您的代码,请重新格式化以删除多余的空白。
@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class Increments {

    private long[] primes;

    @Setup
    public void setup() {
        primes = new long[] {3, 5, 7, 11, 13, 17, 19, 23};
    }

    @Benchmark
    @Fork(1)
    public List<Integer> inc() {
        List<Integer> answers = new ArrayList<>();
        for (int i = 3; i < 100; i++) {
            int bit = i % 32;
            int cur = i / 32;
            long test = (primes[cur] >> bit) & 1;
            if (test == 1) {
                answers.add(i);
            }
        }
        return answers;
    }

    @Benchmark
    @Fork(1)
    public List<Integer> addOne() {
        List<Integer> answers = new ArrayList<>();
        for (int i = 3; i < 100; i+=1) {
            int bit = i % 32;
            int cur = i / 32;
            long test = (primes[cur] >> bit) & 1;
            if (test == 1) {
                answers.add(i);
            }
        }
        return answers;
    }

    @Benchmark
    @Fork(1)
    public List<Integer> addTwo() {
        List<Integer> answers = new ArrayList<>();
        for (int i = 3; i < 100; i+=2) {
            int bit = i % 32;
            int cur = i / 32;
            long test = (primes[cur] >> bit) & 1;
            if (test == 1) {
                answers.add(i);
            }
        }
        return answers;
    }
}
Benchmark          Mode  Cnt    Score    Error  Units
Increments.addOne  avgt    5  304,670 ± 73,226  ns/op
Increments.addTwo  avgt    5  131,429 ± 13,616  ns/op
Increments.inc     avgt    5  249,329 ± 14,866  ns/op
i+=2  131ns
i++   249ns
i+=1  304ns