2017-08-22 1 views
1

floor dans Haskell est défini uniquement pour la classe de type RealFrac. Je ne sais pas vraiment beaucoup de choses sur ce type de classe et le reste de mon code n'utilise que des nombres à virgule flottante.La meilleure façon d'implémenter le plancher et de fracturer des nombres à virgule flottante dans Haskell?

Je ne trouve aucune fonction permettant de transformer un Float en Int. S'il y avait alors floor équivaudrait à fromIntegral (fromFloating x) et fract seraient définis comme

fract x = x - floor x 

Cependant, comme je le disais, je ne l'ai pas trouvé de fonction qui fait quelque chose comme ce que je veux fromFloating à faire. Donc, c'est la seule façon que je pouvais penser à la mise en œuvre fract:

fract x 
    | x < 0 = 1 - fract (abs x) 
    | x < 1 = x 
    | otherwise = fract (x - 1) 

et bien sûr floor x serait x - fract x. L'algorithme ci-dessus, cependant, est O (n) et il va ralentir considérablement les choses, donc j'espère qu'il y a un moyen de faire cela, c'est le temps constant.

+0

'fonction floor' a le type suivant' étage :: (RealFrac a, b intégrale) => a -> b', vous pouvez instanciez-le pour prendre un 'Float' et retourner un' Int' (https://www.haskell.org/hoogle/?hoogle=floor) – Euge

+0

Notamment, Float et Double sont des instances de RealFrac, donc vos soucis que vous utilisez eux au lieu d'utiliser RealFrac est mal placé. – amalloy

+0

Pourquoi pas 'fract = snd. properFraction'? ('fract = \ x -> x - fromIntegral (étage x)' a le bon type et fait presque ce que vous voulez, mais ne fonctionne pas pour les nombres négatifs). Il est tout à fait inutile de 'jeter' un 'Float' à un 'Int' ici (ce que 'casting' signifie réellement pour vous). – user2407038

Répondre

1

Comme le disent les commentaires, floor est déjà implémenté pour les nombres à virgule flottante, et frac est simple; ce code compile:

aDouble :: Double 
aDouble = -5.675 

aFloat :: Float 
aFloat = 10.675 

frac :: RealFrac a => a -> a 
frac x = x - fromIntegral (floor x :: Integer) 

main :: IO() 
main = do 
    putStrLn "aDouble is" 
    print aDouble 
    putStrLn "frac(aDouble) is" 
    print (frac aDouble) 
    putStrLn "aFloat is" 
    print aFloat 
    putStrLn "frac(aFloat) is" 
    print (frac aFloat) 

et produit:

$ runhaskell /tmp/a.hs 
aDouble is 
-5.675 
frac(aDouble) is 
0.3250000000000002 
aFloat is 
10.675 
frac(aFloat) is 
0.6750002