How does Julia compute big numbers?
For example, this works as expected:
julia> 10^18
1000000000000000000
But for bigger numbers, there is a problem with integers:
julia> 10^19
-8446744073709551616
julia> 10^20
7766279631452241920
But it works if a decimal number is used:
julia> 10.0^20
1.0e20
Do you know why?
Check this documentation page: https://docs.julialang.org/en/release-0.4/manual/integers-and-floating-point-numbers/
As you can see, Int64 have a max length of: 2^63 - 1 ~ 1.0 * 10^19
So your 10^19 is greater than this max value. That's why there is a problem.
You can try to convert your 10 to another type.
10.0^20 works because 10.0 is a float, so it has a superior max value.
If you want unlimited precision for integers, you can use BigInts:
julia> BigInt(10)^100
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Related
In Julia shell when I want to calculate some big numbers it returns zero for some of them and non zero for others.
julia> 23^1023
-7505274568781129817
julia> 23^10233345345345345345345345
-524211381283076585
julia> 6^66
0
julia> 6^666567
0
julia> 6^666567467456456
0
why? as I know when a number is greater than it's double of it's variable capacity it's value will be zero. But it's not in this way.
This is integer overflow, see the manual https://docs.julialang.org/en/v1/manual/integers-and-floating-point-numbers/#Overflow-behavior.
You can use Big Integers instead (see https://docs.julialang.org/en/v1/manual/integers-and-floating-point-numbers/#Arbitrary-Precision-Arithmetic):
julia> big"23"^1023
11157740226766098642576916479985732502550079026659668602369253176154754608347999114910934288598509169938542322634035543168104589454551803554752143514808871856407739044413061564710593969809293170387198434732839849079475397354914324959462224192710277582733000707189017630945088977603741349278943158891431873760538457405883290110683119304669609980551503814930814431431975534991573062542027069568527398640080137783572573628744292934799926441803784257928864905102312768281505257318699158791253710647692433095043904635807704217468279561767861663146318198088623674770926880080210309989765622294999800807236464408766346103653985201759420509533876924909908750714069885590356229608446855366913940019430671619981625609206032799826735265432172679241233520172523125869020169711024904402773853129665351797759891642127264888666794316949688983939775549154259963104480736117124292892646814620494489503114758819943362183681467998652454547183948074914858274708971403049788805953569337415595467715850757595901742734059151188466480831121544684493340167911965220743922762612303000346811165975512651283076102510848811008182559770140939825724297406037953883140920313402683491853674438512331534910835550559414659803452756567465225399126516307745943694271055034096963098307296535723190502271598318692446343365508448643996409450204836382025575710687700606126899558525256788416497673251704346550625698638155949249669830567
etc.
Let's say I have a vector
v = Any[1,2,3,4]
And I would like to recompute its eltype in such a way that
typeof(v) = Vector{Int}
Is it possible to accomplish this without having to manually concatenate each of the elements in v?
You can't "retype" the existing v, just create a copy of it with the more concrete type1.
Conversion
Assuming you already (statically) know the result type, you have multiple options. Most readable (and IMO, idiomatic) would be
Vector{Int}(v)
which is almost equivalent to
convert(Vector{Int}, v)
except that the latter does not copy if the input types is already the target type. Alternatively:
convert.(Int, v)
which surely copies as well.
What to convert to
If you don't know what the "common type" would be, there are multiple options how to get one that matches. In general, typejoin can be used to find a least upper bound:
mapreduce(typeof, typejoin, v; init=Union{})
The result will most likely be abstract, e.g. Real for an array of Ints and Float64s. So, for numeric types, you might be better off with promote_type:
mapreduce(typeof, promote_type, v; init=Union{}) # or init=Number
This at least gives you Float64 for mixed Ints and Float64s.
But all of this is not really recommended, since it might be fragile, surprising, and is certainly not type stable.
1For certain combinations of types, with compatible binary form, reinterpret will work and return a view with a different type, but this is only possible for bits types, which Any is not. For converting Any[1,2,3] to Int[1,2,3] copying is fundamentally necessary because the two arrays have different layouts in memory: the former is an array of pointers to individually allocated integers objects, whereas the latter stores the Int values inline in contiguous memory.
If you don't know the output type, then consider using a comprehension
foo(v) = [x for x in v]
This is considerably faster on my computer than identity.(v):
julia> v = Any[1,2,3,4];
julia> #btime foo($v);
153.018 ns (2 allocations: 128 bytes)
julia> #btime identity.($v);
293.908 ns (5 allocations: 208 bytes)
julia> #btime foo(v) setup=(v=Any[rand(0:9) for _ in 1:1000]);
1.331 μs (2 allocations: 7.95 KiB)
julia> #btime identity.(v) setup=(v=Any[rand(0:9) for _ in 1:1000]);
25.498 μs (494 allocations: 15.67 KiB)
This is a quick and dirty trick that usually solves the problem
julia> v = Any[1,2,3,4]
4-element Array{Any,1}:
1
2
3
4
julia> identity.(v)
4-element Array{Int64,1}:
1
2
3
4
I would like to convert a floating point number to a string, retaining the original format of the digits. Here are some ideas I have tried:
julia> VERSION
v"1.0.3"
Notice the format with 9 digits before decimal point:
julia> x = 123456789.123;
These two attempts changed the format:
julia> string(x)
"1.23456789123e8"
julia> repr(x)
"1.23456789123e8"
Here is what I would like:
julia> to_string(x)
## 123456789.123
This seems simple, but I have not found a way to do it.
Any suggestions?
I've run across a little problem when trying to solve a Project Euler problem in Julia. I've basically written a recursive function which produces fractions with increasingly large numerators and denominators. I don't want to post the code for obvious reasons, but the last few fractions are as follows:
1180872205318713601//835002744095575440
2850877693509864481//2015874949414289041
6882627592338442563//4866752642924153522
At that point I get an OverflowError(), presumably because the numerator and/or denominator now exceeds 19 digits. Is there a way of handling 'Big' fractions in Julia (i.e. those with BigInt-type numerators and denominators)?
Addendum:
OK, I've simplified the code and disguised it a bit. If anyone wants to wade through 650 Project Euler problems to try to work out which question it is, good luck to them – there will probably be around 200 better solutions!
function series(limit::Int64, i::Int64=1, n::Rational{Int64}=1//1)
while i <= limit
n = 1 + 1//(1 + 2n)
println(n)
return series(limit, i + 1, n)
end
end
series(50)
If I run the above function with, say, 20 as the argument it runs fine. With 50 I get the OverflowError().
Julia defaults to using machine integers. For more information on this see the FAQ: Why does Julia use native machine integer arithmetic?.
In short: the most efficient integer operations on any modern CPU involves computing on a fixed number of bits. On your machine, that's 64 bits.
julia> 9223372036854775805 + 1
9223372036854775806
julia> 9223372036854775805 + 2
9223372036854775807
julia> 9223372036854775805 + 3
-9223372036854775808
Whoa! What just happened!? That's definitely wrong! It's more obvious if you look at how these numbers are represented in binary:
julia> bitstring(9223372036854775805 + 1)
"0111111111111111111111111111111111111111111111111111111111111110"
julia> bitstring(9223372036854775805 + 2)
"0111111111111111111111111111111111111111111111111111111111111111"
julia> bitstring(9223372036854775805 + 3)
"1000000000000000000000000000000000000000000000000000000000000000"
So you can see that those 63 bits "ran out of space" and rolled over — the 64th bit there is called the "sign bit" and signals a negative number.
There are two potential solutions when you see overflow like this: you can use "checked arithmetic" — like the rational code does — that ensures you don't silently have this problem:
julia> Base.Checked.checked_add(9223372036854775805, 3)
ERROR: OverflowError: 9223372036854775805 + 3 overflowed for type Int64
Or you can use a bigger integer type — like the unbounded BigInt:
julia> big(9223372036854775805) + 3
9223372036854775808
So an easy fix here is to remove your type annotations and dynamically choose your integer types based upon limit:
function series(limit, i=one(limit), n=one(limit)//one(limit))
while i <= limit
n = 1 + 1//(1 + 2n)
println(n)
return series(limit, i + 1, n)
end
end
julia> series(big(50))
#…
1186364911176312505629042874//926285732032534439103474303
4225301286417693889465034354//3299015554385159450361560051
I just read a post from Quora:
http://www.quora.com/Is-Julia-ready-for-production-use
At the bottom, there's an answer said:
2 ^ 3 ^ 4 = 0
I tried it myself:
julia> 2 ^ 3 ^ 4
0
Personally I don't consider this a bug in the language. We can add parenthesis for clarity, both for Julia and for our human beings:
julia> (2 ^ 3) ^ 4
4096
So far so good; however, this doesn't work:
julia> 2 ^ (3 ^ 4)
0
Since I'm learning, I'd like to know, how Julia evaluate this expression to 0? What's the evaluation precedent?
julia> typeof(2 ^ 3 ^ 4)
Int64
I'm surprised I couldn't find a duplicate question about this on SO yet. I figure I'll answer this slightly differently than the FAQ in the manual since it's a common first question. Oops, I somehow missed: Factorial function works in Python, returns 0 for Julia
Imagine you've been taught addition and multiplication, but never learned any numbers higher than 99. As far as you're concerned, numbers bigger than that simply don't exist. So you learned to carry ones into the tens column, but you don't even know what you'd call the column you'd carry tens into. So you just drop them. As long as your numbers never get bigger than 99, everything will be just fine. Once you go over 99, you wrap back down to 0. So 99+3 ≡ 2 (mod 100). And 52*9 ≡ 68 (mod 100). Any time you do a multiplication with more than two factors of 10, your answer will be zero: 25*32 ≡ 0 (mod 100). Now, after you do each computation, someone could ask you "did you go over 99?" But that takes time to answer… time that could be spent computing your next math problem!
This is effectively how computers natively do arithmetic, except they do it in binary with 64 bits. You can see the individual bits with the bits function:
julia> bits(45)
"0000000000000000000000000000000000000000000000000000000000101101"
As we multiply it by 2, 101101 will shift to the left (just like multiplying by 10 in decimal):
julia> bits(45 * 2)
"0000000000000000000000000000000000000000000000000000000001011010"
julia> bits(45 * 2 * 2)
"0000000000000000000000000000000000000000000000000000000010110100"
julia> bits(45 * 2^58)
"1011010000000000000000000000000000000000000000000000000000000000"
julia> bits(45 * 2^60)
"1101000000000000000000000000000000000000000000000000000000000000"
… until it starts falling off the end. If you multiply more than 64 twos together, the answer will always zero (just like multiplying more than two tens together in the example above). We can ask the computer if it overflowed, but doing so by default for every single computation has some serious performance implications. So in Julia you have to be explicit. You can either ask Julia to check after a specific multiplication:
julia> Base.checked_mul(45, 2^60) # or checked_add for addition
ERROR: OverflowError()
in checked_mul at int.jl:514
Or you can promote one of the arguments to a BigInt:
julia> bin(big(45) * 2^60)
"101101000000000000000000000000000000000000000000000000000000000000"
In your example, you can see that the answer is 1 followed by 81 zeros when you use big integer arithmetic:
julia> bin(big(2) ^ 3 ^ 4)
"1000000000000000000000000000000000000000000000000000000000000000000000000000000000"
For more details, see the FAQ: why does julia use native machine integer arithmetic?