Skip to content

(Data.Fixed.mod' n d) not less than d

If one encounters the expression mod' n d, one might reasonably assume that the result of the expression is less than d. However, this is not true:

$ ghci
>>=mod' 3.154831645792668e16 (2 * pi)
8.0

The definition of mod' reveals the problem (when a is an IEEE float):

mod' :: (Real a) => a -> a -> a
mod' n d = n - (fromInteger f) * d where
    f = div' n d

Substituting:

mod' 3.154831645792668e16 (2 * pi)
->
3.154831645792668e16 - (fromIntegral 5021070510506425) * (2 * pi)
->
3.154831645792668e16 - 3.1548316457926672e16
->
8.0

We can repair mod' if we're willing to add a Fractional constraint:

mod' :: (Fractional a, Real a) => a -> a -> a
mod' n d =
    let dr = toRational d
        nr = toRational n
        qt = toRational $ floor (nr / dr)
    in fromRational (nr - (qt * dr))

>>= mod' 3.154831645792668e16 (2 * pi)
6.177334810858532

The advantage of a definition like this is that it yields a correct result. The disadvantages are worse performance and the additional Fractional constraint. Perhaps it would be easier to define div'', mod'', and divMod'' or similar?

Edited by Travis Whitaker
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information