Haskell中的大数距离NaN结果,仅在函数求值中

Haskell中的大数距离NaN结果,仅在函数求值中,haskell,numbers,Haskell,Numbers,我似乎有一个距离公式,当直接运行时效果很好,但当作为函数运行时效果不好。我有: data Point = Point Int Int deriving (Ord, Eq, Show) distance :: Point -> Point -> Double distance (Point x1 y1) (Point x2 y2) = sqrt $ fromIntegral $ ((x2 - x1) ^ 2) + ((y2 - y1) ^ 2) ghci中的跑步距离0点0

我似乎有一个距离公式,当直接运行时效果很好,但当作为函数运行时效果不好。我有:

data Point = Point Int Int
  deriving (Ord, Eq, Show)

distance :: Point -> Point -> Double

distance (Point x1 y1) (Point x2 y2) =
  sqrt $ fromIntegral $ ((x2 - x1) ^ 2) + ((y2 - y1) ^ 2)
ghci中的跑步距离0点0点357356081635 896342957994。 但是,从整型$357356081635^2+896342957994^2替换并直接运行sqrt$会产生一个有用的数值结果:9.649528835269391e11

为什么??谢谢QuickCheck找到了这个

想想看

在Int中进行平方和减法运算-因此将溢出并得到负值,然后将其传递给平方根:

> let x1 = 0 :: Int
> let y1 = 0 :: Int
> let x2 = 357356081635 :: Int
> let y2 = 896342957994 :: Int
> ((x2-x1) ^ 2) + ((y2 - y1) ^ 2)
-2233181682604143571
正如你所看到的,你得到了一个负数

ghci中的第二个部分足够智能,可以采用正确的类型,因为您没有以任何方式约束它try:t

您可以通过将fromIntegral引入内部来实现这一点:

> sqrt $ (fromIntegral x2 - fromIntegral x1)^2 + (fromIntegral y2 - fromIntegral y1) ^ 2
9.649528835269391e11   
补充说明 他在下面的精彩评论中补充了这一点:


为了评估具有多态文字的表达式,ghci必须选择一种类型。在这个 在这种情况下,大数字用整数表示,整数是一种任意精度的类型 以一些开销为代价的整数。使用:set-fwarn type defaults将在中警告您 当这种行为出现时,ghci。如本答案所建议的,使用双打是一种更好的选择 解决方案,因为结果无论如何都是双倍的。还有一个更好的计算路径 这个

想想看

在Int中进行平方和减法运算-因此将溢出并得到负值,然后将其传递给平方根:

> let x1 = 0 :: Int
> let y1 = 0 :: Int
> let x2 = 357356081635 :: Int
> let y2 = 896342957994 :: Int
> ((x2-x1) ^ 2) + ((y2 - y1) ^ 2)
-2233181682604143571
正如你所看到的,你得到了一个负数

ghci中的第二个部分足够智能,可以采用正确的类型,因为您没有以任何方式约束它try:t

您可以通过将fromIntegral引入内部来实现这一点:

> sqrt $ (fromIntegral x2 - fromIntegral x1)^2 + (fromIntegral y2 - fromIntegral y1) ^ 2
9.649528835269391e11   
补充说明 他在下面的精彩评论中补充了这一点:


为了评估具有多态文字的表达式,ghci必须选择一种类型。在这个 在这种情况下,大数字用整数表示,整数是一种任意精度的类型 以一些开销为代价的整数。使用:set-fwarn type defaults将在中警告您 当这种行为出现时,ghci。如本答案所建议的,使用双打是一种更好的选择 解决方案,因为结果无论如何都是双倍的。还有一个更好的计算路径 这个


为了评估具有多态文字的表达式,ghci必须选择一种类型。在这种情况下,大数字表示为任意精度整数的类型,代价是一些开销。当出现这种行为时,使用:set-fwarn type defaults将在ghci中警告您。如本答案中所建议的,使用双倍是一个更好的解决方案,因为结果无论如何都是双倍的。还有一个更好的计算路径。好吧-也许正确的类型有点误导或完全错误-谢谢你的评论-介意我把它包括在答案中,或者你想把它作为你自己的吗?谢谢-我认为基于Int的计算有一些溢出,但不明白ghci是怎么做的。正如Carsten所建议的那样,我已经运行了:t sqrt$from integral$357356081635^2+896342957994^2,但是结果类型并不能帮助我理解我需要做什么才能让函数工作。如果fromIntegral是最好的选择,那就是我要做的。我没有,继续。这只是一个微小的精度。在实践中,使用我使用的正确标志-Wall知道它就在那里是很有用的。在进行减法运算之前,您应该先执行fromIntegral,因为减法运算也会溢出。要使用多态文字对表达式求值,ghci必须选择一种类型。在这种情况下,大数字表示为任意精度整数的类型,代价是一些开销。当出现这种行为时,使用:set-fwarn type defaults将在ghci中警告您。如本答案中所建议的,使用双倍是一个更好的解决方案,因为结果无论如何都是双倍的。还有一个更好的计算路径。好吧-也许正确的类型有点误导或完全错误-谢谢你的评论-介意我把它包括在答案中,或者你想把它作为你自己的吗?谢谢-我认为基于Int的计算有一些溢出,但不明白ghci是怎么做的。正如Carsten所建议的那样,我已经运行了:t sqrt$from integral$357356081635^2+896342957994^2,但是结果类型并不能帮助我理解我需要做什么才能让函数工作。如果fromIntegral是最好的选择,那就是我要做的。我没有,继续。这只是一个微小的精度。知道它在那里,并使用我使用的正确标志-Wall在实践中是有用的。你应该在减法之前做fromIntegral,因为减法也可能溢出。