我正在项目euler上执行question 62,并提出了以下方法来测试数字是否为立方:

isInt x = x == fromInteger (round x)
isCube x= isInt $ x**(1/3)

但是由于浮点错误,它返回不正确的结果:
*Main> isCube (384^3)
False

有没有办法实现更可靠的多维数据集测试?

顺便说一句,这是我的解决方案的其余部分,由于filter (isCube) (perms n)上的类型接口(interface)错误而无法使用:
cubes = [n^3|n<-[1..]]
perms n = map read $ permutations $ show n :: [Integer]
answer = head [n|n<-cubes,(length $ filter (isCube) (perms n)) == 5]

我需要怎么做才能解决该错误?
No instances for (Floating Integer, RealFrac Integer)
   arising from a use of `isCube' at prob62.hs:10:44-49

任何优化也欢迎;-)

最佳答案

尽量避免使用浮点数,尤其是当您遇到有关整数值的问题时。浮点数在取整方面存在问题,某些值(如1/3)无法准确表示。因此,您得到神秘的答案也就不足为奇了。

首先,为了修复您的类型错误,您必须重新定义isCube。如果您检查它的类型签名,则如下所示:

isCube :: (RealFrac a, Floating a) => a -> Bool

请注意,它的第一个参数是Floating类。您的问题是您要在整数值上使用此函数,并且整数不是Floating的实例。您可以像这样重新定义isCube来进行功能类型检查。
isCube x = isInt $ (fromIntegral x) ** (1/3)

但是,那不会使您的程序正确。

使程序更正确的一种方法是执行Henrik的建议。它看起来像这样:
isCube x = (round (fromIntegral x ** (1/3))) ^ 3 == x

祝你好运!

10-08 06:47