list - 在 Haskell 中实现余弦定律?
问题描述
只要其绝对值大于 0.001,该函数就应该返回该值。
但是,我的代码似乎有一些我不知道如何修复的类型错误。我已经尝试将所有类型更改为 Double,但它仍然不起作用。
fac :: Int -> Int
fac n = if (n == 0) then 1 else n * fac (n-1)
cos :: Double -> Double
cos x = sum [cos| k <- [0..],
let cos = (-1) * (x^(2*k) `div` fac (2*k)) ,
abs (cos) > 0.001]
这是错误:
• 无法将预期类型“Double”与实际类型“Int”匹配</p>
• 在'div'的第二个参数中,即'fac (2 * k)'</p>
解决方案
这里基本上有两个问题:
div
仅用于整数除法(即采用整数输入,并通过向下舍入产生整数输出)。你想要(/)
浮点除法。fac
返回一个Int
,您必须在除法中使用之前将其显式转换为浮点数。(许多语言会自动从整数类型转换为浮点类型,但 Haskell 不会。)您可以使用fromIntegral
来转换。
修复这两件事,但没有别的,我们得到:
fac :: Int -> Int
fac n = if (n == 0) then 1 else n * fac (n-1)
cos :: Double -> Double
cos x = sum [cos| k <- [0..],
let cos = (-1) * (x^(2*k) / fromIntegral (fac (2*k))) ,
abs (cos) > 0.001]
这个类型检查,虽然它有几个其他问题,按照从最重要到最不重要的顺序:
- 您可能希望 Haskell 会以某种方式神奇地知道,
abs cos <= 0.001
在一次迭代中,它会在所有未来的迭代中继续如此,并停止迭代。但事实并非如此。您说要从 中k
提取[0..]
,因此它将k
从整个列表中提取——永远不会完成。你可能会喜欢takeWhile
。 - 你失去了
k
上的指数-1
! - 即使不考虑这是否是最有效的公式,您的实现也会重复大量工作。每次调用都
fac (2*k)
必须重新计算它之前所做的所有阶乘作为中间结果;并且您x^(2*k)
重复了一些工作(尽管程度要小得多)。 - 重用名称
cos
是相当混乱的。虽然它在技术上不会使程序出错,但我会避免它。
我把它留给你去探索 Haskell 并学习如何自己解决这些问题——我认为这完全在你在这里展示的能力范围内!
推荐阅读
- python - 在网格上获取像素邻域平均值的有效方法
- python - 使用python将实体名称分散在多行大文本文件中时如何提取实体名称
- php - php Include - 文件夹中的文件
- java - 打开 CSV Performance 写入数据
- swiftui - Swiftui:子视图没有收到对 observableobject 的更新
- python - 在 SQL 中使用 Python 中的多个数据库
- java - 如果选中复选框,则设置 JPanel 可见
- javascript - mach 以 Array 开头的 javascript
- r - 如何在R中没有嵌套for循环的情况下迭代一组函数?
- arrays - 如何比较MongoDB中同一对象的数组元素?