2010-10-19 12 views
15

ten kod działa:Integer unosić

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

Ale to nie działa:

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

Rozumiem, że operacja '/' nie do zdefiniowania typu Integer, ale don” t wiedzieć, jak naprawić kod do pracy z parametrami Integer.

+0

Zobacz również http://stackoverflow.com/questions/1397210/haskell-converting-float-to-int –

+0

A także http: //stackoverflow.com/questions/3275193/whats-the-right-way-to-divide-two-values-to-obtain-a-float –

Odpowiedz

22

Jeśli chcesz wykonać podział ułamkową, można konwertować z dowolnego Integral typu przy użyciu fromIntegral lub fromInteger do konwertowania tylko z Integer specjalnie.

Istnieją podobne funkcje odnoszące się do innych klas typ liczbowy: toRational, fromRational, realToFrac, itd. I oczywiście można konwertować typy ułamkowych z powrotem do integralnych typach korzystających round, floor, ceiling lub takie.

I wreszcie, na off szansa, że ​​faktycznie chciał całkowitą podział, zamiast podziału frakcyjnej z zaokrągleniem potem, nie ma funkcji div i quot (w zależności od tego, co chcesz obcięcia zachowanie).

Ponadto, prawdopodobnie powinieneś napisać swoją funkcję jako coś w rodzaju posToXY a b = round $ a/b. Niepotrzebne do i wiele linii utrudnia czytanie.

+0

'posToXY ab = round $ a/b' - w tym przypadku, ja osobiście wolę nawiasy w celu uzyskania czytelności - oszczędza to konieczności myślenia (nawet przez ułamek sekundy) o pierwszeństwie operatora, a to po prostu wygląda bardziej jak wyrażenie matematyczne, które reprezentuje. – mokus

+0

@mokus: Tak, zgadzam się. Użyłem tylko '($)' tutaj z przyzwyczajenia, prawdopodobnie użyłbym nawiasów w aktualnym kodzie. –

+0

@ C.A.McCann * 'prawdopodobnie powinieneś napisać swoją funkcję jako ...' * - czy sugerujesz lepsze połączenie dwóch funkcji w jedną? – Wolf

7

Można użyć fromIntegral do konwersji dowolnego typu Integral na dowolny typ Num. Więc:

let y = fromIntegral a/fromIntegral b 
7

Twój kod może być łatwo uprościć do

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

Następnie

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

Jeśli chcesz podzielić się liczbą całkowitą, możesz użyć div.

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

Uwaga to nie jest to samo, co zaokrąglania podział zmiennoprzecinkową, ponieważ div zawsze zaokrągla w dół.

Na bardziej ogólnym podpisu typu, można to zrobić zamiast

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