質問
私は、プロジェクトのオイラーの質問62 にやって思い付いたのです数が立方であるかどうかをテストするには、次:
isInt x = x == fromInteger (round x)
isCube x= isInt $ x**(1/3)
しかしによる浮動小数点エラーのために、それは誤った結果を返します:
*Main> isCube (384^3)
False
より信頼性の高いキューブのテストを実施する方法はありますか?
サイドノートでは、こちらのfilter (isCube) (perms n)
のタイプのインターフェイスエラーの動作しません私の解決策、残りのです
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)
しかし、あなたのプログラムが正しいことはありません。
あなたのプログラムは、より正確にする一つの方法は、ヘンリックが提案何をすることです。それは次のようになります:
isCube x = (round (fromIntegral x ** (1/3))) ^ 3 == x
グッドラック!
他のヒント
ハスケルについてあまり知らないが、私は、立方根を取るnearerst整数に丸める、キューブを取り、元の値に比較します。
Integer
値のために有用な別のアプローチのためには、<のhref = "http://hackage.haskell.org/package/arithmoi-0.4.0.3/docs/Math-NumberTheory-Powers-でintegerCubeRoot
機能を見てみましょうCubes.html」のrel = "nofollowを"> arithmoiパッケージでます。
例:
ghci> import Math.NumberTheory.Powers.Cube
ghci> let x = 12345^3333
ghci> length $ show x
13637
ghci> isCube x
True
ghci> isCube (x+1)
False
ghci> length $ show $ integerCubeRoot x
4546
perms
はタイプ[Integer]
を持っています。 isCube
は(あなたがGHCiの中で確認することができますよう)型(RealFrac a, Floating a) => a -> Bool
を持っています。 RealFrac
制約がround x
から来て、Floating
制約がx**(1/3)
から来ています。 Integer
のでどちらRealFrac
もFloating
、isCube
はののできないInteger -> Bool
として使用することです。だから、filter isCube (perms n)
は意味がありません。
ですから、isCube
sで正常に動作するようにInteger
を修正する必要があります:
isCube x = isInt $ (fromInteger x)**(1/3)
実際には、isCube (384^3)
もコンパイルの理由は、それが「本当に」isCube ((fromInteger 384)^(fromInteger 3))
を意味していることである。
もちろん、これはまだによる浮動小数点エラーのためにひどく動作します。基本的に、あなたがisInt
でそうであるように、平等のための数値を浮動チェックし、ほとんど常に悪い考えです。より良いテストを作成する方法を説明するために他の回答を参照してください。