I’m a python user doing scientific computing. I’m also interested in julia, and tried it after v1.0 released.
I haven’t start learning julia yet, only tried it as a simple calculator, and get some unexpected result.
Evenviroment:
julia Version 1.0.0 (2018-08-08)
Python 3.6.5 |Anaconda custom (64-bit)
Ubuntu 18.04
The reason is simple: the int64 type of julia has a max value of 2^63-1.
I don’t know if this should be considered as a bug, but the result is really unexpected.
A warning or an error would be much better.
Tell me some thing went wrong is better than return the misleading result without a warning.
Compare with Python:
the int type of python seems can be unlimited large.
the float type has a max value of 1.7976931348623157e+308.
When the value is out of range, it will return a OverflowError.
>>> 10**23*10**-23
0.9999999999999999
>>> 10.0**23*10.0**-23
0.9999999999999999
>>> 10**23
100000000000000000000000
>>> 10.0**23
1e+23
>>> 10**1000 + 1
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
>>> 10.0**1000 + 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: (34, 'Numerical result out of range')
>>> 10**1000 + 1.0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: int too large to convert to float
>>> type(1)
<class 'int'>
>>> type(1.0)
<class 'float'>
>>> import sys
>>> sys.float_info.max
1.7976931348623157e+308
julia> BigInt(10^1000) + 1
1
julia> BigFloat(10.0^1000) + 1
Inf
julia> BigInt(10)^BigInt(1000) + 1
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
julia> BigFloat(10.0)^BigInt(1000) + 1
1.000000000000000000000000000000000000000000000000000000000000000000000000000004e+1000
julia> BigInt(10)^BigInt(23)*BigInt(10)^BigInt(-23)
ERROR: DomainError with -23:
`y` cannot be negative.
Stacktrace:
[1] bigint_pow(::BigInt, ::BigInt) at ./gmp.jl:504
[2] ^(::BigInt, ::BigInt) at ./gmp.jl:525
[3] top-level scope at none:0
julia> BigInt(10)^BigInt(23)*BigInt(10)^-BigInt(23)
ERROR: DomainError with -23:
`y` cannot be negative.
Stacktrace:
[1] bigint_pow(::BigInt, ::BigInt) at ./gmp.jl:504
[2] ^(::BigInt, ::BigInt) at ./gmp.jl:525
[3] top-level scope at none:0
julia> BigInt(10)^BigInt(23)*BigInt(10)^BigFloat(-23)
1.0
I need to put every single number in BigInt() or BigFloat() to get the right ans.
With SaferIntegers.jl, I also need to put every single number in SafeInt().
This seems kinda silly to me.
julia> 10^BigInt(23)*10^BigFloat(-23)
1.0
julia> SafeInt8(127) * 2
ERROR: OverflowError: 127 * 2 overflowed for type Int8
And I wouldn’t say that the explicitness is silly. In the worst case you can call it inconvenient but only if you are using Julia not as a programming language but as a glorified calculator in which you have to enter a myriad of number literals.
You are using BigFloat which has limited precision:
10^BigFloat(1000) and 10^BigFloat(1000)+1 are the same BigFloat number so
(10^BigFloat(1000) + 1 ) - 10^BigFloat(1000) is zero,
then
((10^BigFloat(1000) + 1 ) - 10^BigFloat(1000)) - 1 is -1
You would need 1000 decimals of precision for this computation:
Edit: also python does not have a native big float type, so it will fail to convert a large integer to a float, whereas julia converts BigInt to BigFloat which explains the python error.
I am still trying to figure this one out. Even though they are within the default relative precision of BigFloat which you can check with the eps method:
julia> a=BigFloat(10^BigInt(309))
1.000000000000000000000000000000000000000000000000000000000000000000000000000005e+309
julia> b=10^BigInt(309)
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
julia> @which a+b
+(x::BigFloat, c::BigInt) in Base.MPFR at mpfr.jl:349
It is using a MPFR method (most specific dispatch) to operate on mixed types and not going through promotions, so this explains the observations. As long as it is within the expected precision this is good but it was surprising to me.