我正在项目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
祝你好运!