What's the right way to divide two Int values to obtain a Float?

27,785

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
Share:
27,785
Wyzard
Author by

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, 2020

Comments

  • Wyzard
    Wyzard about 4 years

    I'd like to divide two Int values in Haskell and obtain the result as a Float. 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 a Ratio Integer, so the operands need to be of type Integer rather than Int. But the values I'm dividing are nowhere near the Int 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
    Wyzard almost 14 years
    Thanks, that makes sense. I'd wondered if I could convert to Float first, but somehow managed to overlook fromIntegral 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 a Rational from the integers, which doesn't lose precision.)
  • Chuck
    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, while Ratio Int and Ratio Integer are both different types. You may have intended toRational.
  • Wyzard
    Wyzard almost 14 years
    @Chuck: Rational is an alias for Ratio Integer, and (%) returns a Ratio of whatever type its operands are, so applying it to two Integer should produce a Rational (unless I'm misunderstanding). My problem was that I was giving it Int and producing Ratio Int (which is indeed not a Rational).
  • Hans-Kristian Norum Eidesen
    Hans-Kristian Norum Eidesen almost 14 years
    @Wyzard: You can convert here using fromIntegral again ... It's quite generic.