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
beachten Sie, dass x
hat den Typ einer generic Nummer. Sie es mit nur Operationen berechnet, die für jede Nummerntyp arbeiten, wenn Sie eine solche Nummer in GHCi bewerten, wird standardmäßig die “ sichersten ” Betontyp, der Integer
ist, ein beliebiger Präzisionstyp, der bei großen Zahlen kein Problem hat. Sie können jedoch die Berechnung erzwingen zu mit einem anderen numerischen Typ erfolgen:
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
Die Gleitkomma-Versionen sind ungenau, aber immer noch nahe, während Int
(eine maschine feste Größe Präzision Nummer) einfach überläuft und gibt kompletten Schein .
Normalerweise stört Sie das nicht, da große Berechnungen standardmäßig mit dem sicheren Typ Integer
durchgeführt werden.
Das ist, es sei denn, etwas anderes verhindert es.
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
Im Gegensatz zu x
, ist die Art der y
bereits konkret: es Int
sein muss, denn das ist der Ergebnistyp von length
ist. (Die Begründung Wesen: eine Liste, die so groß ist, dass man nicht seine Länge mit einem Int
messen könnte, wäre im Speicher nicht in der Lage sein, auf jeden Fall passen.)
Nun div
, wie die meisten numerischen Funktionen in Haskell, erfordern, dass die Argumente und Ergebnis haben alle denselben Typ. Aus diesem Grund wird x`div`y
als Ganzes als Int
anstelle von Integer
berechnet, einschließlich x
. Und wie wir gesehen haben, gibt die Berechnung x
als Int
betrügerisch.
OTOH, wenn Sie 362880
als Literal verwenden, dann ist dies nicht mit length
verbunden. Es ist nur eine allgemeine Zahl, wie x
, daher wird GHCi wieder standardmäßig sicher Integer
, dh Sie
Prelude Data.List> x `div` 362880
2658017764500203964000
Das gleiche Ergebnis erreicht werden kann, wenn man nur Umwandlung von y
erlauben:
Prelude Data.List> x `div` fromIntegral y
2658017764500203964000
es ist nur die "Länge" drin - dies wird das Ergebnis auf "Int" beschränken, aber Sie wollen wirklich "Integer" - verwenden Sie '(\ j -> fromIntegral $ length j)' was nur 'fromIntegral ist. Länge statt – Carsten
als Alternative könnten Sie auch ['genericLength'] (https://hackage.haskell.org/package/base-4.8.2.0/docs/Data-List.html#v:genericLength) verwenden, um – Carsten
btw: das letzte Parth ist wirklich seltsam, da der letzte Teil nur "[9]" usw. ist. – Carsten