我试图执行以下计算: x:y范围内整数的平方和,其中(x <= y)。
我不确定如何设置约束以确保x小于或等于y。
我需要能够将x的平方加到x + 1:y范围内的平方和中。
我看了几个例子,但是找不到任何严格说明第一个数字必须小于或等于第二个数字,即[1..5]
更新:为了澄清,我不想在函数中硬编码[1..5],但我希望列表是用户的输入。
任何帮助?
由于
答案 0 :(得分:6)
明显而缓慢的方法是实际求和这些方格:
sumOfSquaresSlow :: Integral a => a -> a -> a
sumOfSquaresSlow lo hi
| lo > hi = error "sumOfSquaresSlow: lo > hi"
| otherwise = sum $ map (^2) [lo..hi]
这种方法的时间复杂度在max(y-x,0)中是线性的;如果你的整数范围很大,则需要一段时间;在我的答案底部看到基准。
但是,因为前n个(正)整数的平方和有一个formula,所以你实际上不必逐个对这些正方形求和。
如果x
大于y
(在your comment中指定),则向用户发出错误消息,您只需使用error
功能,此处为
(编辑:感谢Chris Drost pointing out that I was overcomplicating things)
sumOfSquaresFast :: Integral a => a -> a -> a
sumOfSquaresFast lo hi
| lo > hi = error "sumOfSquaresFast: lo > hi"
| otherwise = ssq hi - ssq (lo - 1)
where
ssq x = div (((2 * x + 3) * x + 1) * x) 6
使用此公式可以将复杂性降低到接近恒定时间的程度。
λ> :set +s
λ> sumOfSquaresSlow (10^3) (10^7)
333333383333002166500
(17.19 secs, 11563005552 bytes)
λ> sumOfSquaresFast (10^3) (10^7)
333333383333002166500
(0.01 secs, 3106112 bytes)
答案 1 :(得分:2)
在GHCI中,请执行以下步骤,了解正在进行的操作:
Prelude> let sq x = x^2
Prelude> let list = [1..5]
Prelude> list
[1,2,3,4,5]
Prelude> let listOfSq = map sq list
Prelude> listOfSq
[1,4,9,16,25]
Prelude> sum listOfSq
55
简写就是Jubobs所说的:
sum $ map (^2) [1..5]
编辑:要在Y大于X时出错,你可以做类似的事情
sumOfSquares :: Integer -> Integer -> Integer
sumOfSquares x y | y <= x = error "Y must be greater than X"
| otherwise = sum $ map (^2) [x..y]
答案 2 :(得分:-1)
使用列表理解:
squareSum from to
| from > to = error "wrong input"
| otherwise = sum [i^2 | i <- [from..to]]
更新:OP更新问题后更新