在Haskell中实现余弦定律?
Implement the law of cosine in Haskell?
所以我想用这个公式创建我自己的余弦函数:
只要绝对值大于0.001,函数就应该return这个值。
但是,我的代码似乎有一些我不知道如何修复的类型错误。我已经尝试将所有类型更改为 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”相匹配
• 在‘div’的第二个参数中,即‘fac(2 * k)’
这里基本上有两个问题:
div
仅用于整数除法(即采用整数输入,并通过向下舍入产生整数输出)。您想要 (/)
进行浮点除法。
fac
returns 和 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
在一次迭代中,它会在所有未来的迭代中继续如此,并停止迭代。但事实并非如此。您说要从 [0..]
中抽取 k
,因此它将从整个列表中抽取 k
——永远不会完成。您可能更喜欢 takeWhile
。
- 您在
-1
上丢失了指数 k
!
- 即使不考虑这是否是最有效的入手公式,您的实施也会重复很多工作。对
fac (2*k)
的每次调用都必须重新计算它之前完成的所有阶乘作为中间结果;并且您的 x^(2*k)
重复了一些工作(尽管程度要小得多)。
- 重复使用名称
cos
非常令人困惑。虽然从技术上讲它不会使程序 错误 ,但我会避免它。
我留给你探索 Haskell 和学习如何自己解决这些问题的乐趣 -- 我认为这完全在你在这里展示的能力范围内!
所以我想用这个公式创建我自己的余弦函数:
只要绝对值大于0.001,函数就应该return这个值。
但是,我的代码似乎有一些我不知道如何修复的类型错误。我已经尝试将所有类型更改为 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”相匹配
• 在‘div’的第二个参数中,即‘fac(2 * k)’
这里基本上有两个问题:
div
仅用于整数除法(即采用整数输入,并通过向下舍入产生整数输出)。您想要(/)
进行浮点除法。fac
returns 和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
在一次迭代中,它会在所有未来的迭代中继续如此,并停止迭代。但事实并非如此。您说要从[0..]
中抽取k
,因此它将从整个列表中抽取k
——永远不会完成。您可能更喜欢takeWhile
。 - 您在
-1
上丢失了指数k
! - 即使不考虑这是否是最有效的入手公式,您的实施也会重复很多工作。对
fac (2*k)
的每次调用都必须重新计算它之前完成的所有阶乘作为中间结果;并且您的x^(2*k)
重复了一些工作(尽管程度要小得多)。 - 重复使用名称
cos
非常令人困惑。虽然从技术上讲它不会使程序 错误 ,但我会避免它。
我留给你探索 Haskell 和学习如何自己解决这些问题的乐趣 -- 我认为这完全在你在这里展示的能力范围内!