2010-10-19 15 views
15

Questo codice funziona:Integer galleggiare

posToXY :: Float -> Float -> Integer 
posToXY a b = do 
     let y = a/b 
     round y 

Ma questo non funziona:

posToXY :: Integer -> Integer -> Integer 
posToXY a b = do 
     let y = a/b 
     round y 

ho capito che l'operazione '/' non definisce per tipo Integer, ma I don' so come risolvere il codice per lavorare con i parametri Integer.

+0

Vedi anche http://stackoverflow.com/questions/1397210/haskell-converting-float-to-int –

+0

E anche http: //stackoverflow.com/questions/3275193/whats-the-right-way-to-divide-two-int-values-to-obtain-a- float –

risposta

22

Se si desidera eseguire la divisione frazionaria, è possibile convertire da qualsiasi tipo Integral utilizzando fromIntegral, o fromInteger per convertire solo da Integer in particolare.

ci sono funzioni simili relativi ad altre classi di tipo numerico: toRational, fromRational, realToFrac, ecc E, naturalmente, è possibile convertire i tipi frazionali di nuovo a tipi interi che utilizzano round, floor, ceiling, o tali.

E, infine, sulla remota possibilità che in realtà voleva intero divisione, invece di divisione frazionaria con arrotondamento poi, ci sono i div e quot funzioni (a seconda di quale comportamento troncamento che si desidera).

Inoltre, probabilmente dovresti scrivere la tua funzione come qualcosa come posToXY a b = round $ a/b. L'inutile do e più righe rende più difficile la lettura.

+0

'posToXY ab = round $ a/b' - in questo caso, personalmente preferisco le parentesi per la leggibilità - si evita di dover pensare (anche solo per una frazione di secondo) sulla precedenza degli operatori, e sembra proprio l'espressione matematica che rappresenta. – mokus

+0

@mokus: Sì, sono d'accordo. Ho usato solo '($)' qui per abitudine, probabilmente avrei usato parentesi nel codice reale. –

+0

@ C.A.McCann * 'probabilmente dovresti scrivere la tua funzione come ...' * - stai suggerendo di unire meglio le due funzioni in una? – Wolf

7

È possibile utilizzare fromIntegral per convertire qualsiasi tipo di Integrale in qualsiasi tipo di Num. Quindi:

let y = fromIntegral a/fromIntegral b 
7

Il codice potrebbe facilmente essere semplificata per

posToXY :: Float -> Float -> Integer 
posToXY a b = round (a/b) 

Poi

posToXY :: Integer -> Integer -> Integer 
posToXY a b = round (fromIntegral a/fromIntegral b) 
3

Se si desidera la divisione intera, è possibile utilizzare div.

posToXY :: Integer -> Integer -> Integer 
posToXY = div 

Nota questo non è del tutto identica a arrotondamento una divisione in virgola mobile, perché div arrotonda sempre verso il basso.

per una firma più generale tipo, si può fare questo, invece

p :: (Real a, Real a1, Integral b) => a -> a1 -> b 
posToXY a b = round (realToFrac a/realToFrac b)