2017-03-13 3 views
1

ich in Haskell Funktion Wich geschrieben hat zählt pi Zahl mit Präzision als Parameter angegeben:Rückgabewert ist Null, wenn der Parameter mehr als 7 Nullen

mojePi :: Integer -> Float 
mojePi x = sqrt $ 6 * mySum x 
    where 
     mySum 1 = 1 
     mySum x = sum $ map (1/) $ map (**2) [y,y-1..1] 
      where 
       y = fromInteger x 

Wenn ich diese Funktion mit 10000000 (7 Nullen) laufen, es funktioniert, aber mit 100000000 (8 Nullen) und mehr gibt es sofort 0 zurück. Warum passiert es?

Antwort

4

Hier ist der Grund:

> let y :: Float ; y = fromInteger (100000000 :: Integer) 
> y == y-1 
True 
> [y, y-1 .. 1] 
[] 

Grundsätzlich ist ein Float nicht von 10^8 nach unten bis 1, mit Einheitsschritten zählen kann.

Rundungsfehler machen yy-1 und die gleiche Anzahl, daher die Bezeichnung [y,y-1 .. 1] als zunehmende Sequenz interpretiert wird, wie z.B. [10,10 .. 1]. Da der Startwert bereits über 1 liegt, wird kein Element in die Ausgabeliste aufgenommen.

Zitiert aus dem Haskell 2010 report:

Die Sequenz enumFromThenTo e1 e2 e3 ist die Liste [e1,e1 + i,e1 + 2i,…e3], wo der Zuwachs, i, e2 − e1 ist. Wenn das Inkrement positiv oder Null ist, endet die Liste, wenn das nächste Element größer als e3 wäre; Die Liste ist leer, wenn e1 > e3. Wenn das Inkrement negativ ist, wird die Liste beendet, wenn das nächste Element kleiner als e3 wäre; Die Liste ist leer, wenn e1 < e3.

Wahrscheinlich sollte Haskell unterschiedliche Bezeichnungen für steigende und fallende Bereiche haben. Für [y, y-1 .. 1], ich denke, repeat y wäre eine weniger überraschende Ausgabe als [].

+1

Es könnte sich lohnen, ''y, y-1 .. 1]' '' '' 'zu erklären. Abschnitt [6.3.4 Die Enum-Klasse] (https://www.haskell.org/onlinereport/haskell2010/haskellch6.html#x13-1310006.3.4) geht ins Detail. Ich war mir all dieses Verhaltens nicht bewusst. – Alec

+0

@Alec In der Tat, ich denke ich habe es jetzt auch herausgefunden! Hinzugefügt. – chi

Verwandte Themen