2016-04-01 7 views
4
(product (take 9 [1000,999..])) `div` (product (map (\j-> product [1..j]) (map (\j->length(j)) (group [2,2,2,2,2,2,2,2,2])))) 

マイナスになる上記のコードは、私がコピーして、GHCiの中にコードを貼り付けた場合、それは答えとして私を-12740133310672与えX=product (take 9 [1000,999..]) & Y=(product (map (\j-> product [1..j]) (map (\j->length(j)) (group [2,2,2,2,2,2,2,2,2]))))多数はHaskellで

と形X div Y、であり、 私がX & Yと数えれば964541486381834014456320000 & 362880となり、それを分割すると答えは2658017764500203964000になります。

数値が大きすぎるためだと思いますが、コンピュータがXとYを正しく個別に計算できるので、どうやってそれらを組み合わせることもできません。整数の代わりのIntを使用して

+5

をこれはちょうどそこの長さです - これは結果を 'Int'に制限しますが、本当に' Integer'が必要です - 'fromIntegralだけの'(\ j - > fromIntegral $ length j) 'を使います。代わりに – Carsten

+4

の代わりに['genericLength'](https://hackage.haskell.org/package/base-4.8.2.0/docs/Data-List.html#v:genericLength)を使用することもできます。 – Carsten

+1

btw:最後のparthは本当に奇妙です。最後の部分は '[9]'などです。 – Carsten

答えて

10
Prelude Data.List> let x = product $ take 9 [1000,999..] 

Prelude Data.List> x 
964541486381834014456320000 
Prelude Data.List> :t x 
x :: (Enum a, Num a) => a 

xジェネリック数の種類があることを確認:あなたはGHCiの中で、このような数を評価するとき、それは最も安全な“デフォルト、あなたが任意の数値型のためを働くだけの操作でそれを計算します。 ”具体的なタイプはIntegerであり、大きな数字に問題のない任意精度の型。単に完全偽をオーバーフローし、得られる浮動小数点バージョンはInt(機械サイズの固定精度数)に対し、不正確まだ近い

Prelude Data.List> x :: Integer 
964541486381834014456320000 
Prelude Data.List> x :: Float 
9.645414e26 
Prelude Data.List> x :: Double 
9.645414863818342e26 
Prelude Data.List> x :: Int 
-4623139575776374784 

:ただし、他の数値型で行われるべき計算を強制することができ。

巨大な計算はデフォルトで安全なIntegerタイプで行われるため、通常これで問題はありません。

つまり、何か他のことができない限り、それはありません。

Prelude Data.List> let y = product (map (\j-> product [1..j]) $ map length (group [2,2,2,2,2,2,2,2,2])) 

Prelude Data.List> y 
362880 
Prelude Data.List> :t y 
y :: Int 

xとは異なり、yの種類は、すでに具体的なある:それはIntでなければならない、それはlengthの結果タイプだから。 (その理由は、あなたが長さを測ることができないほど大きいリストで、Intはメモリに収まらないでしょう)

今、divは、Haskellのほとんどの数値関数と同様に、引数と結果はすべて同じ型です。このため、x`div`yは、Integerxを含む)の代わりに、Intとして全体として計算されます。これまで見てきたように、xIntと計算すると、偽になります。

OTOHの場合、362880をリテラルとして使用すると、lengthに接続されません。それはxのように、単に一般的な数ですが、それゆえGHCiのは、再び安全Integerにデフォルト設定されます、あなたはちょうど変換y許可した場合、同じ結果を達成することができ

Prelude Data.List> x `div` 362880 
2658017764500203964000 

を取得すなわち:

Prelude Data.List> x `div` fromIntegral y 
2658017764500203964000 
+0

Uhh - 私は、実際には文字通りの結果を貼り付けたことを知っています。今はすべてが理にかなっています!素晴らしい答え! – robert

0

ができます:

let r :: Integer ; r = (product (take 9 [1000,999..])) `div` (product (map (\j-> product [1..j]) (map (\j->fromIntegral $ length(j)) (group [2,2,2,2,2,2,2,2,2])))) 

は私を取得します。2658017764500203964000

私は完全にあなたのコードを理解していないが、私はあなたがそれらを個別に計算する場合は、小さい中間結果を得ることを前提と - そうIntはオーバーフローしません。

したがって、incoherenceは大きな数値のためint型は幅が限られているので、オーバーフローします(負数)。このような大きな数値で操作する場合は、無制限の幅を持つIntegerを使用してください。

+0

ハスケルは最初にXとYを計算していないでしょうか? Haskellはそれらを個別に計算することができるので、どのようにしてXを計算できないのですか? – CYC

+0

いいえ、それはありません。あなたの個人的な計算は私のためには機能しません - 私は後で確認しなければなりません。 – robert