2010-10-19 8 views
15

Este código funciona:entero a flotar

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

Pero esto no funciona:

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

entiendo que la operación '/' no define de tipo entero, pero yo no' Saber cómo corregir el código para trabajar con los parámetros de Integer.

+0

Véase también http://stackoverflow.com/questions/1397210/haskell-converting-float-to-int –

+0

Y también http: //stackoverflow.com/questions/3275193/whats-the-right-way-to-divide-two-int-values-to-obtain-a-float –

Respuesta

22

Si desea realizar la división fraccional, se puede convertir de cualquier tipo Integral usando fromIntegral, o fromInteger para convertir solo de Integer específicamente.

Hay algunas funciones similares para otras clases de tipo numérico: toRational, fromRational, realToFrac, etc, y por supuesto que puede convertir los tipos de fracciones de nuevo a tipos integrales utilizando round, floor, ceiling, o algo así.

Y, por último, en la remota posibilidad de que en realidad quería número entero división, en lugar de la división fraccional con redondeo después, están los div y quot funciones (dependiendo de lo que el comportamiento de truncamiento que desee).

Además, probablemente deba escribir su función como algo así como posToXY a b = round $ a/b. La innecesaria do y las líneas múltiples hacen que sea más difícil de leer.

+0

'posToXY ab = redondo $ a/b' - en este caso, personalmente prefiero paréntesis para la legibilidad, ahorra tener que pensar (incluso por una fracción de segundo) sobre la precedencia del operador, y se parece más a la expresión matemática que representa. – mokus

+0

@mokus: Sí, estoy de acuerdo. Solo usé '($)' aquí por costumbre, probablemente hubiera usado paréntesis en el código real. –

+0

@ C.A.McCann * 'probablemente deberías escribir tu función como ...' * - ¿estás sugiriendo combinar mejor las dos funciones en una sola? – Wolf

7

Puede usar fromIntegral para convertir cualquier tipo Integral en cualquier tipo Num. Por lo tanto:

let y = fromIntegral a/fromIntegral b 
7

Su código fácilmente podría simplificarse en

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

Entonces

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

Si desea una división entera, puede usar div.

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

cuenta que esto no es exactamente lo mismo que el redondeo una división de punto flotante, porque div siempre redondea hacia abajo.

Para una firma de tipo más general, se puede hacer esto en vez

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