Целое число для плавания
Этот код работает:
posToXY :: Float -> Float -> Integer
posToXY a b = do
let y = a / b
round y
Но это не работает:
posToXY :: Integer -> Integer -> Integer
posToXY a b = do
let y = a / b
round y
Я понимаю, что операция '/' не определена для типа Integer, но я не знаю, как исправить код для работы с параметрами Integer.
Ответы
Ответ 1
Если вы хотите выполнить дробное деление, вы можете конвертировать из любого типа Integral
с помощью fromIntegral
или fromInteger
для преобразования только из Integer
.
Существуют похожие функции, относящиеся к другим классам с числовым типом: toRational
, fromRational
, realToFrac
и т.д. И, конечно, вы можете преобразовать дробные типы обратно в интегральные типы с помощью round
, floor
, ceiling
или такой.
И, наконец, вовремя, что вы действительно хотели целое деление, вместо дробного деления с округлением впоследствии функции div
и quot
(в зависимости от того, какое поведение усечения вы хотите).
Кроме того, вы, вероятно, должны написать свою функцию как нечто вроде posToXY a b = round $ a / b
. Необязательные do
и несколько строк затрудняют чтение.
Ответ 2
Вы можете использовать fromIntegral
для преобразования любого интегрального типа в любой тип Num. Итак:
let y = fromIntegral a / fromIntegral b
Ответ 3
Ваш код может быть легко упрощен до
posToXY :: Float -> Float -> Integer
posToXY a b = round (a / b)
Тогда
posToXY :: Integer -> Integer -> Integer
posToXY a b = round (fromIntegral a / fromIntegral b)
Ответ 4
Если вам требуется целочисленное деление, вы можете использовать div
.
posToXY :: Integer -> Integer -> Integer
posToXY = div
Обратите внимание, что это не совсем то же самое, что округление деления с плавающей запятой, потому что div
всегда округляется вниз.
Для более общей сигнатуры типа вы можете сделать это вместо
p :: (Real a, Real a1, Integral b) => a -> a1 -> b
posToXY a b = round (realToFrac a / realToFrac b)