2011-10-25 34 views
4

好吧,也许这里一个愚蠢的问题,但我目前通过完成projecteuler.net指数经营者业绩

我遇到了一个有趣的观察问题的学习Haskell和希望有人能提供一些线索为什么事情的方式,他们是。

仅供参考,我正在执行Problem #29 这里就是我想出了

nub $ [ a^^b | a <- [2..100], b <- [2..100] ] 

我观察到使用^^操作快于**^上面列出的输入速度更快。

我的问题很简单,为什么?每个这些运算符都适用于不同的类型类别。我的猜测是发生了一些类型转换,但我认为^是更快的操作,当它看起来实际上是反例。

谢谢!

+1

如果列表不是很短(这是不是),不要使用结点,这是O(n^2)。 –

+3

有Haskell中没有类型转换。 –

回答

4

所有的时间都花在nub上。随着^^**你在[Double]上做nub。与^它是nub[Integer],比较大整数慢于比较双打。

+0

对,'nub'在这个例子中做了所有的工作,谢谢你的解释。 – Jake

4

**^^正在使用Double,但^正在使用Integer。你真的无法将浮点运算与大整数函数进行比较。看看implementation of ^

在你的代码,以下是真:

  • **在硬件中实现。
  • ^在尾递归循环中使用大Integer
  • ^^是一样的,除了Double

因此,你对他们的相对表现的观察是有道理的。

1

我在处理Project Euler问题时发现的事情是,类型可以使运行时性能发生巨大变化。例如:

foo :: Integral a => a -> a 
foo' :: Integer -> Integer 
foo'' :: Int -> Int 

都有很不同的表现。想象一下,当我发现简单地让编译器推断出foo的最通用类型,而不是自己指定它,导致性能较差时,我很惊讶。

性能也(显然)高度依赖于您的环境:您正在运行编译或解释?优化还是未优化?问题是,在某些情况下,你可能已经拆箱,原始的Int# s在封面下而不是装箱,堆分配值...不幸的是,我仍然足够的一个n00b我自己,我不知道你什么时候会得到一个vs.其他:(

所以,也许这是一个愚蠢的答案,但如果你使用GHC和你熟悉C语言编程,尝试使用-keep-hc-files标志当您使用^比较它们生成的中间的C代码。^^**

+0

当编译器看到Ints是严格需要的时候,你会得到Int#,你可以帮助使用爆炸模式,但是检查核心是否你有他们,并衡量它是否真的有帮助另一个说明,.hc文件只能由未注册的编译器生成(用户指南),所以大多数人都不会拥有它们。 –