Haskell 中过度使用 fromIntegral

发布于 2024-09-13 13:52:14 字数 369 浏览 9 评论 0原文

每当我使用双精度和整数编写函数时,我都会发现这个问题,我必须在函数中的任何地方不断地使用“fromIntegral”。例如:

import Data.List

roundDouble
    :: Double
    -> Int 
    -> Double
roundDouble x acc = fromIntegral (round $ x * 10 ** fromIntegral acc) / 10 ** fromIntegral acc

有没有更简单的写法? (我知道可能有更简单的方法来对数字进行四舍五入,如果有请告诉我!但是我主要感兴趣的是如何避免使用这么多“fromIntegrals”。)

谢谢,Ash

Whenever I write a function using doubles and integers, I find this problem where I am constantly having to use 'fromIntegral' everywhere in my function. For example:

import Data.List

roundDouble
    :: Double
    -> Int 
    -> Double
roundDouble x acc = fromIntegral (round $ x * 10 ** fromIntegral acc) / 10 ** fromIntegral acc

Is there an easier way of writing this? (I know there may be easier ways of rounding a number and if there are please let me know! However I am mainly interested in how to avoid using so many 'fromIntegrals'.)

Thanks, Ash

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

ゃ人海孤独症 2024-09-20 13:52:14

有时我发现辅助函数很有用:

roundDouble x acc = (round $ x * 10 ^ acc) /. (10 ^ acc)
    where 
    x /. y = fromIntegral x / fromIntegral y

该辅助函数也可以编写为:

(/.) = (/) `on` fromIntegral

Where on is from Data.Function

Sometimes I find a helper function useful:

roundDouble x acc = (round $ x * 10 ^ acc) /. (10 ^ acc)
    where 
    x /. y = fromIntegral x / fromIntegral y

That helper function can also be written:

(/.) = (/) `on` fromIntegral

Where on is from Data.Function.

难得心□动 2024-09-20 13:52:14

您可以使用 ^ 代替 **^ 将任何 Integral 作为第二个参数,因此您无需对第二个操作数调用 fromIntegral。所以你的代码变成:

roundDouble x acc = fromIntegral (round $ x * 10 ^ acc) / 10 ^ acc

其中只有一个 fromIntegral。而您无法摆脱的那个,因为 round 自然会返回一个 Integral,并且您无法对 Integral 执行非整数除法。

You can use ^ instead of **. ^ takes any Integral as it's second argument, so you don't need to call fromIntegral on the second operand. So your code becomes:

roundDouble x acc = fromIntegral (round $ x * 10 ^ acc) / 10 ^ acc

Which has only one fromIntegral. And that one you can't get rid off as round naturally returns an Integral and you can't perform non-integer division on an Integral.

So要识趣 2024-09-20 13:52:14

我对封送代码也有类似的问题,其中 fromIntegral 用于将 CInt 转换为 Int。我通常定义 fI = fromIntegral 以使其更容易。您可能还需要为其提供显式类型签名或使用 -XNoMonomorphismRestriction。

如果您需要进行大量数学运算,则可能需要查看 数值Prelude,它似乎在不同数字类型之间有更合理的关系。

I have a similar problem with marshaling code, where fromIntegral is used to convert CInt to Int. I usually define fI = fromIntegral to make it easier. You may also need to give it an explicit type signature or use -XNoMonomorphismRestriction.

If you're doing a lot of math, you may want to look at the Numeric Prelude, which seems to have much more sensible relations between different numeric types.

海夕 2024-09-20 13:52:14

另一个想法,类似于luqui的。我与 fromIntegral 相关的大多数问题都与将 Int 除以 DoubleDouble 除以 Int 的必要性有关。因此,这个 (/.) 允许划分任意两个 Real 类型,不一定相同,也不一定是 Integral 类型,如 luqui 的解决方案中所示:

(/.) :: (Real a, Real b, Fractional c) => a -> b -> c
(/.) x y = fromRational $ (toRational x) / (toRational y)

示例:

ghci> let (a,b,c) = (2::Int, 3::Double, 5::Int)
ghci> (b/.a, c/.a, a/.c)
(1.5,2.5,0.4)

它适用于任何两个Real,但我怀疑有理数除法和与Rational之间的转换不是很有效。

现在你的例子变成:

roundDouble :: Double -> Int -> Double
roundDouble x acc = (round $ x * 10 ^ acc) /. (10 ^ acc)

Another idea, similar to luqui's. Most of my problems with fromIntegral are related to necessity to divide Int by Double or Double by Int. So this (/.) allows to divide any two Real types, not necessarily the same, an not necessarily Integral types like in luqui's solution:

(/.) :: (Real a, Real b, Fractional c) => a -> b -> c
(/.) x y = fromRational $ (toRational x) / (toRational y)

Example:

ghci> let (a,b,c) = (2::Int, 3::Double, 5::Int)
ghci> (b/.a, c/.a, a/.c)
(1.5,2.5,0.4)

It works for any two Reals, but I suspect that rational division and conversion to/from Rational are not very effective.

Now your example becomes:

roundDouble :: Double -> Int -> Double
roundDouble x acc = (round $ x * 10 ^ acc) /. (10 ^ acc)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文