Итак, я снова взял Project Euler, чтобы немного поиграть с Kotlin. Для тех, кто не знает, Project Euler - это сайт с упражнениями по программированию от банальных до довольно сложных.
В любом случае, самая первая проблема заключается в следующем:
Если мы перечислим все натуральные числа ниже 10, кратные 3 или 5, мы получим 3, 5, 6 и 9. Сумма эти кратные числа равны 23.
Найдите сумму всех кратных 3 или 5 ниже 1000.
Я решил это как последовательно, так и функционально, так как я хотел посмотреть, как они сравниваются:
class ProjectEuler1 {
companion object {
fun sequential(): Int {
var sum = 0
for (i in 1..999)
if (i % 3 == 0 || i % 5 == 0)
sum += i
return sum
}
fun functional(): Int = (1..999).filter { it % 3 == 0 || it % 5 == 0 } .sum()
fun benchmark() {
var solSequential = -1
val tSequential = measureExactTimeMillis { solSequential = sequential() }
var solFunctional = -1
val tFunctional = measureExactTimeMillis { solFunctional = functional() }
println("""
+---
|${this::class.java.canonicalName.replace(".Companion", "")}
+---
|Sequential solution: $solSequential
|Sequential running time: ${tSequential.round(6)} ms
+---
|Functional solution: $solFunctional
|Functional running time: ${tFunctional.round(6)} ms
+---
""".trimIndent())
}
}
}
measureExactTimeMillis
- это просто measureNanoTime
, деленное на 1_000_000
, возвращающее Double
.
В любом случае, после выполнения этого несколько раз, результат всегда был более или менее таким:
+---
|ProjectEuler1
+---
|Sequential solution: 233168
|Sequential running time: 0.6097 ms
+---
|Functional solution: 233168
|Functional running time: 33.3555 ms
+---
Последовательная и, к сожалению, более многословная версия в 50-100 раз быстрее, чем простая функциональная реализация.
В чем причина этого? Разве выступления не должны быть хотя бы сопоставимы (в отличие от порядков величины)? Я что-то упустил, чтобы оптимизировать функциональную реализацию?