質問

私は、プロジェクトのオイラーの質問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のでどちらRealFracFloatingisCubeのできないInteger -> Boolとして使用することです。だから、filter isCube (perms n)は意味がありません。

ですから、isCubesで正常に動作するようにIntegerを修正する必要があります:

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

実際には、isCube (384^3)もコンパイルの理由は、それが「本当に」isCube ((fromInteger 384)^(fromInteger 3))を意味していることである。

もちろん、これはまだによる浮動小数点エラーのためにひどく動作します。基本的に、あなたがisIntでそうであるように、平等のための数値を浮動チェックし、ほとんど常に悪い考えです。より良いテストを作成する方法を説明するために他の回答を参照してください。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top