Haskell 指数算子性能
好的,也许这是一个愚蠢的问题,但我目前正在通过在projecteuler.net上完成问题来学习haskell 我遇到了一个有趣的观察结果,希望有人能解释为什么事情是这样的 作为参考,我正在实施 这是我想到的Haskell 指数算子性能,haskell,Haskell,好的,也许这是一个愚蠢的问题,但我目前正在通过在projecteuler.net上完成问题来学习haskell 我遇到了一个有趣的观察结果,希望有人能解释为什么事情是这样的 作为参考,我正在实施 这是我想到的 nub $ [ a^^b | a <- [2..100], b <- [2..100] ] nub$[a^^b | a***和^^使用的是双精度,但是^使用的是整数。您确实无法将浮点运算与大整数函数进行比较。请看下面的示例 在您的代码中,以下是正确的: **在硬件中实现 ^
nub $ [ a^^b | a <- [2..100], b <- [2..100] ]
nub$[a^^b | a***
和^^
使用的是双精度
,但是^
使用的是整数
。您确实无法将浮点运算与大整数函数进行比较。请看下面的示例
在您的代码中,以下是正确的:
**
在硬件中实现
^
在尾部递归循环中使用大的整数
^
与之相同,只有Double
除外
因此,您对它们的相对性能的观察是有意义的。所有的时间都花在nub
上。使用^
和**
您在[Double]
上做nub
在[Integer]上做就是nub
,比较大整数要比比较双倍整数慢。在处理Project Euler问题时,我发现类型会对运行时性能产生巨大影响。例如:
foo :: Integral a => a -> a
foo' :: Integer -> Integer
foo'' :: Int -> Int
所有这些都有非常不同的性能。当我发现仅仅让编译器推断foo
的最通用类型而不是自己指定它会导致性能低下时,想象一下我的惊讶吧
性能也是(明显的)高度依赖于您的环境:您正在运行编译或解释?优化还是未优化?问题是,在某些情况下,您可能会将未装箱的原始Int
s隐藏在封底下,而不是装箱的堆分配值……不幸的是,我自己仍然是n00b的一员,我不知道您何时会得到一个n00b与其他人相比:(
因此,也许这是一个愚蠢的答案,但是如果您使用GHC并且熟悉C编程,请尝试使用-keep hc files
标志来比较使用^
与^
与^
与**
时生成的中间C代码。对了,nub
正在完成示例中的所有工作。感谢您这么做清楚。如果列表不是很短(事实并非如此),请不要使用nub。它是O(n^2)。Haskell中没有类型转换。当编译器发现严格需要Int时,您将得到Int。您可以帮助使用bang模式,但一定要检查核心是否得到了它们,并衡量它是否真的有帮助。另一方面,.hc文件仅由未注册的编译器生成(《用户指南》),所以大多数人无论如何都不会有。