1. ホーム
  2. java

[解決済み] Scalaでfor-comprehensionとloopを最適化する方法とは?

2022-07-14 09:15:59

質問

ScalaはJavaと同じくらい速くなると言われています。私は今、いくつかの プロジェクト・オイラー の問題に再挑戦しています.特に問題5: "1から20までのすべての数で均等に割り切れる最小の正の数は何でしょうか?

私のマシンでは0.7秒で完了します。

public class P005_evenly_divisible implements Runnable{
    final int t = 20;

    public void run() {
        int i = 10;
        while(!isEvenlyDivisible(i, t)){
            i += 2;
        }
        System.out.println(i);
    }

    boolean isEvenlyDivisible(int a, int b){
        for (int i = 2; i <= b; i++) {
            if (a % i != 0) 
                return false;
        }
        return true;
    }

    public static void main(String[] args) {
        new P005_evenly_divisible().run();
    }
}

これが私のScalaへの直訳で、103秒かかります(147倍!)。

object P005_JavaStyle {
    val t:Int = 20;
    def run {
        var i = 10
        while(!isEvenlyDivisible(i,t))
            i += 2
        println(i)
    }
    def isEvenlyDivisible(a:Int, b:Int):Boolean = {
        for (i <- 2 to b)
            if (a % i != 0)
                return false
        return true
    }
    def main(args : Array[String]) {
        run
    }
}

最後に関数型プログラミングに挑戦してみました。所要時間は39秒(55倍)です。

object P005 extends App{
    def isDivis(x:Int) = (1 to 20) forall {x % _ == 0}
    def find(n:Int):Int = if (isDivis(n)) n else find (n+2)
    println (find (2))
}

Windows 7 64-bit で Scala 2.9.0.1 を使用しています。どのようにパフォーマンスを向上させることができますか?私は何か間違ったことをしているのでしょうか?それとも、Javaはもっと速いのでしょうか?

どのように解決するのですか?

この特定のケースの問題は、for式の中から戻ることです。これは順番に NonLocalReturnException のスローに変換され、囲んだメソッドでキャッチされます。オプティマイザはforeachを排除することはできても、throw/catchを排除することはまだできない。そして、throw/catchは高価である。しかし、Scalaのプログラムではこのようなネストされたリターンはまれなので、オプティマイザはまだこのケースに対処していない。オプティマイザーを改善するための作業が行われており、近いうちにこの問題が解決されることを期待しています。