10
votes

Comment analyser une fraction décimale dans Rational à Haskell?

J'ai participé à Un concours de programmation et L'un des problèmes de problèmes 'Entrée de données comprenait un nombre de fractionnements dans un format décimal: 0,75 est un exemple. < / p>

analyser que dans double est trivial (je peux utiliser lire pour cela), mais la perte de précision est douloureuse. Il faut faire très attention avec Double Comparaisons (je n'étais pas), ce qui semble redondant depuis que l'on a rationnel type de données dans HASKELLL.

Lorsque vous essayez d'utiliser cela, j'ai découvert que lire a rationnel Il faut fournir une chaîne dans le format suivant: numérateur% Denominator < / code>, que je n'ai évidemment pas.

Alors, la question est:

Quel est le moyen le plus simple d'analyser une représentation décimale d'une fraction dans rationnel ?

Le nombre de dépendances externes doit également être pris en compte, car je ne peux pas installer de bibliothèques supplémentaires dans le juge en ligne.


0 commentaires

3 Réponses :


18
votes

La fonction que vous voulez est numeric.readfloat : xxx


1 commentaires

Vous voudrez peut-être ajouter lectusigned si vous souhaitez pouvoir lire des nombres négatifs: fst. tête $ lectures lectures "-3,14" :: rationnelle



3
votes

Que diriez-vous de la section suivante (Session GHCI):

> :m + Data.Ratio
> approxRational (read "0.1" :: Double) 0.01
1 % 10


2 commentaires

C'est une bonne idée! Je pense que cela devrait être utilisé à la place de Tordification dans la plupart des cas!


Malheureusement, le choix de Epsilon n'est pas évident ici. Par exemple, environ 0,999 0,0001 est 909% 910 , ce qui n'est pas ce que je veux. L'epsilon approprié à utiliser dans ce cas est 0.000001 (précision carré?)



2
votes

Peut-être que vous obtiendriez des points supplémentaires dans le concours pour la mettre en œuvre vous-même:

import Data.Ratio ( (%) )

readRational :: String -> Rational
readRational input = read intPart % 1 + read fracPart % (10 ^ length fracPart)
  where (intPart, fromDot) = span (/='.') input
        fracPart           = if null fromDot then "0" else tail fromDot


1 commentaires

Je ne le pense pas. Dans de tels concours, seuls le temps de soumission et l'exactitude compte. Belle solution encore, suffisamment courte pour coder en cas d'urgence.