В качестве продолжения я попробовал флаг -optimize, и он сократил время выполнения с 103 до 76 секунд, но это все равно в 107 раз медленнее, чем Java или цикл while.
Тогда я смотрел на «функциональную» версию:
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))
}
и пытается выяснить, как избавиться от «суеты» в сжатой форме. Я с треском провалился и придумал
object P005_V2 extends App {
def isDivis(x:Int):Boolean = {
var i = 1
while(i <= 20) {
if (x % i != 0) return false
i += 1
}
return true
}
def find(n:Int):Int = if (isDivis(n)) n else find (n+2)
println (find (2))
}
, в результате чего мое хитрое пятистрочное решение увеличилось до 12 строчек. Однако эта версия работает за 0,71 секунды , с той же скоростью, что и исходная версия Java, и в 56 раз быстрее, чем указанная выше версия, используя "forall" (40,2 с)! (см. РЕДАКТИРОВАТЬ ниже, почему это быстрее, чем Java)
Очевидно, что моим следующим шагом было перевести вышеупомянутое обратно в Java, но Java не может с этим справиться и выдает ошибку StackOverflowError с n вокруг отметки 22000.
Затем я немного почесал голову и заменил «while» на более длинную хвостовую рекурсию, которая экономит пару строк, работает так же быстро, но, давайте посмотрим правде в глаза, читать немного сложнее:
object P005_V3 extends App {
def isDivis(x:Int, i:Int):Boolean =
if(i > 20) true
else if(x % i != 0) false
else isDivis(x, i+1)
def find(n:Int):Int = if (isDivis(n, 2)) n else find (n+2)
println (find (2))
}
Итак, хвостовая рекурсия Scala выигрывает день, но я удивлен, что что-то простое, такое как цикл «for» (и метод «forall»), по существу нарушено и должно быть заменено неэлегичным и многословным «whiles», или хвостовая рекурсия. Во многом я пытаюсь использовать Scala из-за лаконичного синтаксиса, но не очень хорошо, если мой код будет работать в 100 раз медленнее!
РЕДАКТИРОВАТЬ : (удалено)
РЕДАКТИРОВАНИЕ РЕДАКТИРОВАНИЯ : Прежние расхождения между временами выполнения от 2,5 с до 0,7 с были полностью обусловлены тем, использовались ли 32-битные или 64-битные JVM. Scala из командной строки использует все, что установлено JAVA_HOME, в то время как Java использует 64-битную версию, если она доступна независимо. IDE имеют свои собственные настройки. Некоторые измерения здесь: Время выполнения Scala в Eclipse