Comment optimiser pour des inclusions et des boucles en Scala?

Scala est censé être aussi rapide que Java. Je suis de revoir certaines Projet Euler problèmes en Scala que j'ai d'abord abordé en Java. Plus précisément Problème 5: "Quel est le plus petit nombre positif qui est divisible par tous les nombres de 1 à 20?"

Voici ma solution Java, qui prend de 0,7 secondes sur ma machine:

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();
    }
}

Voici ma "traduction" en Scala, qui prend 103 secondes (147 fois de plus!)

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
    }
}

Enfin voici ma tentative de programmation fonctionnelle, qui prend en 39 secondes (55 fois plus longtemps)

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))
}

Utilisation de Scala 2.9.0.1 sur Windows 7 64 bits. Comment puis-je améliorer les performances? Suis-je en train de faire quelque chose de mal? Ou est Java il y a beaucoup plus vite?

  • avez-vous la compilation ou de l'interpréter à l'aide de la scala de shell?
  • Il y a une meilleure façon de le faire qu'à l'aide de la section de première instance (Indice).
  • vous n'avez pas de montrer comment vous êtes timing de cette. Avez-vous essayez juste de chronométrage de la run méthode?
  • C'est compilé, pas de coquille.
  • J'ai chronométré juste la méthode de course en utilisant le Système.nanotime() en Java. Un physique chronomètre de la Scala versions
  • yep, juste fait la pen & version papier: écrire les facteurs premiers de chaque numéro du haut, puis traverser les facteurs que vous avez déjà pour les numéros les plus élevés, de sorte que vous avez terminé avec (5*2*2)*(19)*(3*3)*(17)*(2*2)*()*(7)*(13)*()*(11) = 232792560
  • +1 C'est la question la plus intéressante que j'ai vu depuis des semaines sur SO (qui possède également la meilleure réponse que j'ai vu dans un certain temps).
  • +1 pour dire "aussi vite que Java".
  • balle - la mise en œuvre exécutable n'est pas la même chose que "la fraie un nouveau fil de discussion." new Thread(new Runnable() { public void run() { ... } }), cependant, est la même que la reproduction d'un nouveau thread.
  • J'ai l'habitude de mettre en œuvre Praticable dans mes classes Java qui sont destinés à être exécutés: il est plus conceptuel sens que statique "principal" de la méthode, et je peux facilement lancer dans un nouveau thread d'ailleurs (par exemple, un Swing GUI). Mais je devrais probablement avoir oublié pendant cette discussion parce que c'est sans importance lorsque nous utilisons un "principal".

InformationsquelleAutor Luigi Plinge | 2011-05-26