What's the right way to divide two Int values to obtain a Float?
You have to convert the operands to floats first and then divide, otherwise you'll perform an integer division (no decimal places).
Laconic solution (requires Data.Function
)
foo = (/) `on` fromIntegral
which is short for
foo a b = (fromIntegral a) / (fromIntegral b)
with
foo :: Int -> Int -> Float
Wyzard
I no longer contribute to StackExchange sites, because of the company’s unjust treatment and apparent libel of Monica Cellio, as well as the retroactive change of content license without permission from those who own the content. SE no longer seems like a company that I can trust, nor one that I want to support. (Mistake Overflow discusses the same issues, and others.)
Updated on April 21, 2020Comments
-
Wyzard about 4 years
I'd like to divide two
Int
values in Haskell and obtain the result as aFloat
. I tried doing it like this:foo :: Int -> Int -> Float foo a b = fromRational $ a % b
but GHC (version 6.12.1) tells me "Couldn't match expected type 'Integer' against inferred type 'Int'" regarding the
a
in the expression.I understand why: the
fromRational
call requires(%)
to produce aRatio Integer
, so the operands need to be of typeInteger
rather thanInt
. But the values I'm dividing are nowhere near theInt
range limit, so using an arbitrary-precision bignum type seems like overkill.What's the right way to do this? Should I just call
toInteger
on my operands, or is there a better approach (maybe one not involving(%)
and ratios) that I don't know about? -
Wyzard almost 14 yearsThanks, that makes sense. I'd wondered if I could convert to
Float
first, but somehow managed to overlookfromIntegral
while browsing through the docs for all the functions in the various numeric classes. (I don't think the other approach would've done integer division losing decimal places as you alluded to, though: I was making aRational
from the integers, which doesn't lose precision.) -
Chuck almost 14 years@Wyzard: You were not making a Rational from the integers. You were treating the result of the operator as as a Rational, when in fact it was not. Look at the type signature for
fromRational
: the argument is a Rational, whileRatio Int
andRatio Integer
are both different types. You may have intendedtoRational
. -
Wyzard almost 14 years@Chuck:
Rational
is an alias forRatio Integer
, and(%)
returns aRatio
of whatever type its operands are, so applying it to twoInteger
should produce aRational
(unless I'm misunderstanding). My problem was that I was giving itInt
and producingRatio Int
(which is indeed not aRational
). -
Hans-Kristian Norum Eidesen almost 14 years@Wyzard: You can convert here using
fromIntegral
again ... It's quite generic.