Get the decimal part of a number

Is there a function in Base Julia to get the decimal part of a number? I feel like I’ve seen that function before, but now I can’t find it. For example, I would like the following:

julia> x = 12.345;

julia> foo(x)
0.345

Granted, I can get an approximation to that behavior, but I’m looking for a builtin function. If I try x - floor(x), then sometimes I get some floating point wonkiness:

julia> x = 1.3
1.3

julia> x - floor(x)
0.30000000000000004
1 Like

This isn’t floating point wonkiness. This is just that 1.3 != 13//10 The exact value of 1.3 - 1 is 0.30000000000000004.

1 Like

Realize that Julia isn’t printing all of the digits here, just the smallest number of digits that rounds to the same value (because 1.3 isn’t exactly represented in binary floating point). If you print all of the digits you see:

julia> big(1.3)
1.3000000000000000444089209850062616169452667236328125

So 1.3 - 1 (in Float64) is exactly 0.3000000000000000444089209850062616169452667236328125, which gets printed as 0.30000000000000004 for Float64 (double precision). (0.3xxx needs to print one more decimal digit at the end to ensure that it rounds to the same binary-floating point value, because the number of significant decimal places has increased by one compared to 1.3xxx.)

In contrast, 0.3 in double precision rounds to a different binary floating-point value:

julia> big(0.3)
0.299999999999999988897769753748434595763683319091796875

Therefore, 1.3 - 1 != 0.3 is correct.

If you need exact decimals for some reason, you can use decimal floating point via the DecFP.l package:

julia> using DecFP

julia> x = d"1.3"
1.3

julia> x - floor(x)
0.3
4 Likes

See also PSA: floating-point arithmetic

1 Like

By “floating point wonkiness”, I mean floating point numbers behaving correctly but counter-intuitively. Obviously floating point numbers in Julia conform to the IEEE standard.

I thought I had once used the hypothetical function mentioned in my original post, but it must have been a dream I had.

The ‘modf’ function returns a tuple containing fractional and integer parts of a number. Maybe that could be useful to you?

6 Likes

mod(x, 1) works.

Not for negative numbers.

julia> let xs=(3.14, -3.14); modf.(xs) end
((0.14000000000000012, 3.0), (-0.14000000000000012, -3.0))

julia> let xs=(3.14, -3.14); mod.(xs, 1) end
(0.14000000000000012, 0.8599999999999999)

However, mod(x, sign(x)) works:

julia> let xs=(3.14, -3.14); mod.(xs, sign.(xs)) end
(0.14000000000000012, -0.14000000000000012)