Why isn't the "setrounding" function working the way I expect?

Why does Julia rounds 0.3 down in my code?

julia> setrounding(BigFloat, RoundUp)
MPFRRoundUp::MPFRRoundingMode = 2

julia> BigFloat(0.3)
0.299999999999999988897769753748434595763683319091796875

The rounding happens to 0.3, which is of type Float64, no?

Try BigFloat("0.3") and see if that’s better.

3 Likes

Thank you, now it is working the way I expect.

julia> setrounding(BigFloat, RoundUp)
MPFRRoundUp::MPFRRoundingMode = 2

julia> BigFloat(“0.3”)
0.3000000000000000000000000000000000000000000000000000000000000000000000000000017

2 Likes

Here Julia is also rounding down, can you help me again?

julia> setrounding(BigFloat, RoundUp)
MPFRRoundUp::MPFRRoundingMode = 2

julia> BigFloat(3/10)
0.299999999999999988897769753748434595763683319091796875

I think your mental model of the order of operations is still a bit off. When you run BigFloat(3 / 10), the first thing that happens is computing 3 / 10. That operation is not affected in any way by the context of being inside a call to BigFloat. But once 3 / 10 has run, the approximation error that confuses you has already been introduced and can’t ever be undone by calling BigFloat. In fact, none of your examples so far have anything to do with calling setrounding(BigFloat, RoundUp): you’re just seeing the effects of applicative order evaluation. To see it more clearly, spend time understanding what happens here:

function f(x)
    println("f!")
    x
end

function g(x)
    println("g!")
    x
end

f(g(1))

You should do something like BigInt(3) / BigInt(10) or big"3" / big"10".

3 Likes

BigFloat(3//10) would also work as 3//10 is a Fraction which is exact.

3 Likes

Float64 uses a binary representation, and it represents a discrete, not continuous set of numbers. 3/10 cannot be represented by a binary number with a finite number of bits. So when you type 0.3 or 3/10, you get the binary number that can be represented as a Float64 and is closest to three tenths. Then you are converting this approximation to a BigFloat.

You don’t see the problem here

julia> BigFloat(1/8)
0.125

because one eighth can be represented exactly as a Float64.

Thank you for explaining, now I understand better how evaluation works in Julia.

1 Like

Yes, BigFloat(3//10) works, I got the output I wanted

julia> setrounding(BigFloat, RoundUp)
MPFRRoundUp::MPFRRoundingMode = 2

julia> BigFloat(3//10)
0.30000000000000000000000000000000000015

When I type any of the following expressions: ‘4.1’, ‘8.1’, ‘129.0’, Julia evaluates then as Float64. Is there any macros that makes Julia evaluate those expressions as BigFloat? Because not only is writing ‘4.1’ more comfortable than writing 'BigFloat(“4.1”), but also makes my code more readable.

You don’t need a macro, just big"4.1"

That is actually implemented as the @big_str macro: https://docs.julialang.org/en/v1/manual/metaprogramming/#Non-Standard-String-Literals-1

3 Likes

Oh, that’s awesome! Thanks for sharing!

2 Likes