On AMD64,
julia> x=[1//1];x.*=1/5
1-element Array{Rational{Int64},1}:
3602879701896397//18014398509481984
but on i386 works correctly. See travis build for this repo for behavior on different platforms.
On AMD64,
julia> x=[1//1];x.*=1/5
1-element Array{Rational{Int64},1}:
3602879701896397//18014398509481984
but on i386 works correctly. See travis build for this repo for behavior on different platforms.
I’m seeing that answer on all my x64 machines.
Intel/Linux:
julia> x=[1//1];x.*=1/5
1-element Array{Rational{Int64},1}:
3602879701896397//18014398509481984
julia> versioninfo()
Julia Version 1.4.0
Commit b8e9a9ecc6 (2020-03-21 16:36 UTC)
Platform Info:
OS: Linux (x86_64-pc-linux-gnu)
CPU: Intel(R) Core(TM) i7-3820 CPU @ 3.60GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-8.0.1 (ORCJIT, sandybridge)
Then on an AMD/Windows:
julia> x=[1//1];x.*=1/5
1-element Array{Rational{Int64},1}:
3602879701896397//18014398509481984
julia> versioninfo()
Julia Version 1.4.0
Commit b8e9a9ecc6 (2020-03-21 16:36 UTC)
Platform Info:
OS: Windows (x86_64-w64-mingw32)
CPU: AMD Ryzen Threadripper 1950X 16-Core Processor
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-8.0.1 (ORCJIT, znver1)
It’s not related to in-place multiplication. It’s because 1/5
is not identical to 0.2:
julia> 1/5 == 1//5
false
julia> big(1/5)
0.200000000000000011102230246251565404236316680908203125
julia> convert(Rational{Int}, 1/5)
3602879701896397//18014398509481984
On any architecture,
julia> x=[Int32(1)//Int32(1)];x.*=1/5
1-element Array{Rational{Int32},1}:
1//5
julia> x=[Int64(1)//Int64(1)];x.*=1/5
1-element Array{Rational{Int64},1}:
3602879701896397//18014398509481984
To expand on what @DNF said, what’s happening is
julia> Rational(1//1 * (1/5))
3602879701896397//18014398509481984
which happens to be correct (although somewhat unexpected if you are not aware of how floating point works). Cf
It’s not related to in-place multiplication anyhow:
julia> Rational{Int32}(0.2)
1//5
julia> Rational{Int64}(0.2)
3602879701896397//18014398509481984
Why don’t you simply use rational numbers when multiplying?
julia> x=[1//1];x.*=1//5
1-element Array{Rational{Int64},1}:
1//5
Relying on conversion of floats to rationals seems pretty brittle.
I see, thanks for setting me straight.
Just to nuance it a bit, it is indirectly related to in-place multiplication, because setindex!
into an Array{T}
will attempt to convert to T
:
julia> a64 = [1//1];
julia> a64[1] = 0.2;
julia> a64
1-element Array{Rational{Int64},1}:
3602879701896397//18014398509481984
julia> a32 = [Int32(1)//Int32(1)];
julia> a32[1] = 0.2;
julia> a32
1-element Array{Rational{Int32},1}:
1//5
For Rational{Int32}
there are no values between 0.2
and 1//5
, but for Rational{Int64}
there is.
Amusingly, for Float32
it’s a different story:
julia> a32[1] = 0.2f0; # this is a Float32 literal
julia> a32
1-element Array{Rational{Int32},1}:
13421773//67108864
Since 0.2f0
is further away from 1//5
than 0.2
is, 13421773//67108864
is able to sneak in between them.
Edit: It actually seems like the rational approximations are exact. I wonder if I understand this correctly:
julia> big(3602879701896397)/big(18014398509481984)
0.200000000000000011102230246251565404236316680908203125
julia> big(0.2e0)
0.200000000000000011102230246251565404236316680908203125
julia> big(13421773)/big(67108864)
0.20000000298023223876953125
julia> big(0.2f0)
0.20000000298023223876953125