2010-07-18 15 views
25

Mi piacerebbe dividere due valori Int in Haskell e ottenere il risultato come Float. Ho provato a fare in questo modo:Qual è il modo giusto per dividere due valori Int per ottenere un Float?

foo :: Int -> Int -> Float 
foo a b = fromRational $ a % b 

ma GHC (versione 6.12.1) dice "tipo non poteva competere previsto 'Integer' contro tipo derivato 'Int'" me per quanto riguarda la a nell'espressione.

capisco perché: la chiamata fromRational richiede (%) per produrre un Ratio Integer, quindi gli operandi devono essere di tipo Integer piuttosto che Int. Ma i valori che sto dividendo non sono neanche lontanamente vicini al limite dell'intervallo Int, quindi usare un tipo bignum di precisione arbitraria sembra eccessivo.

Qual è il modo giusto per farlo? Dovrei semplicemente chiamare toInteger sui miei operandi, o c'è un approccio migliore (forse uno che non riguarda (%) e rapporti) che non conosco?

risposta

32

Devi convertire gli operandi in float prima e quindi dividere, altrimenti eseguirai una divisione intera (senza cifre decimali).

soluzione Laconico (richiede Data.Function)

foo = (/) `on` fromIntegral 

che è breve per

foo a b = (fromIntegral a)/(fromIntegral b) 

con

foo :: Int -> Int -> Float 
+0

Grazie, questo ha un senso. Mi chiedevo se potevo prima convertire in 'Float', ma in qualche modo sono riuscito a ignorare' fromIntegral' mentre sfogliavo i documenti per tutte le funzioni nelle varie classi numeriche. (Non penso che l'altro approccio avrebbe fatto la divisione intera perdendo i decimali come hai fatto allusione, però: stavo facendo un 'Rational' dagli interi, che non perde la precisione.) – Wyzard

+0

@Wyzard: Eri non fare un Razionale dagli interi. Stavi trattando il risultato dell'operatore * come * come un Razionale, quando in realtà non lo era. Osserva la firma del tipo per 'fromRational': l'argomento è un Rational, mentre' Ratio Int' e 'Ratio Integer' sono entrambi tipi diversi. Potresti aver voluto 'toRational'. – Chuck

+0

@Chuck: 'Rational' è un alias per' Ratio Integer', e '(%)' restituisce un 'Ratio' di qualunque tipo siano i suoi operandi, quindi applicarlo a due' Integer' dovrebbe produrre un 'Rational' (a meno che Sto fraintendendo) Il mio problema era che stavo dando 'Int' e producendo' Ratio Int' (che in effetti * non * è 'Razionale'). – Wyzard

Problemi correlati