Julia computation does not give the correct answer [duplicate] - julia

This question already has an answer here:
Why 2 ^ 3 ^ 4 = 0 in Julia?
(1 answer)
Closed 4 months ago.
When I tried to calculate
10^999
in Julia 1.8.2. I got an answer of 0. I think this could be due to the storage issue (10^99 is too large)? But how do we avoid this type of error automatically, is there any way to tell Julia to stop calculating 10^99 instead of returning me a value of 0? I just want to avoid such error in my code.
In fact, if I try to calculate
1E999
Julia will tell me syntax: overflow in numeric constant "1E999", which is what I want. Thanks!

While the reasons have been discussed in comments and there are links to similar questions just not that you could try:
julia> big(10)^99
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
or define your own primitive type
julia> using BitIntegers
julia> BitIntegers.#define_integers 1024
#uint1024_str (macro with 1 method)
julia> Int1024(10)^99
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Related

Is expressing this computation using functional idioms better Julia? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I am learning the Julia language and would like to know which implementation is likely to have better performance.
In answer to question How to check if a string is numeric Julia last answer is
isintstring(str) = all(isdigit(c) for c in str)
This code works well, but it could be rewritten
isintstring = str -> mapreduce(isnumeric, &, collect(str))
Is the rewrite better or worse? or just different? The Julia Style Guide does not seem to provide guidance.
Edit: As originally expressed, this question was blocked for seeking opinion not facts. I have rephrased it in gratitude for the three outstanding and helpful answers the original question received.
If you are using collect there is probably something wrong with your code, especially if it's a reduction. So your second method needlessly allocates, and, furthermore, it does not bail out early, so it will keep going to the end of the string, even if the first character fails the test.
If you benchmark the performance, you will also find that mapreduce(isnumeric, &, collect(str)) is an order of magnitude slower, and that is without considering early bailout.
In general: Don't use collect(!), and bail out early if you can.
The idiomatic solution in this case is
all(isdigit, str)
Edit: Here are some benchmarks:
jl> using BenchmarkTools, Random
jl> str1 = randstring('0':'9', 100)
"7588022864395669501639871395935665186290847293742941917566300220720077480508740079115268449616551087"
jl> str2 = randstring('a':'z', 100)
"xnmiemobkalwiiamiiynzxxosqoavwgqbnxhzaazouzbfgfbiodsmhxonwkeyhxmysyfojpdjtepbzqngmfarhqzasppdmvatjsz"
jl> #btime mapreduce(isnumeric, &, collect($str1))
702.797 ns (1 allocation: 496 bytes)
true
jl> #btime all(isdigit, $str1)
82.035 ns (0 allocations: 0 bytes)
true
jl> #btime mapreduce(isnumeric, &, collect($str2))
702.222 ns (1 allocation: 496 bytes) # processes the whole string
false
jl> #btime all(isdigit, $str2)
3.500 ns (0 allocations: 0 bytes) # bails out early
false
The rewrite is definitely worse. Slower, less elegant and more verbose.
Another edit: I only noticed now that you are using isnumeric with mapreduce, but isdigit with all. isnumeric is more general and much slower than isdigit so that also makes a big difference. If you use isdigit instead, and remove collect, the speed difference isn't so big for numeric strings, but it still does not bail out early for non-numeric strings, so the best solution is still clearly all(isdigit, str).
Part of your question is about named vs anonymous functions. In the first case, you created a function via its first method and assigned it to an implicitly const variable isintstring. The function object itself also gets the name isintstring, as you can see in its type. You can't reassign the variable isintstring:
julia> isintstring(str) = all(isdigit(c) for c in str)
isintstring (generic function with 1 method)
julia> typeof(isintstring)
typeof(isintstring)
julia> isintstring = str -> mapreduce(isnumeric, &, collect(str))
ERROR: invalid redefinition of constant isintstring
julia> isintstring = 1
ERROR: invalid redefinition of constant isintstring
Now let's restart the REPL and switch the order to start at the second case. The second case creates an anonymous function, then assigns it to a variable isintstring. The anonymous function gets a generated name that can't be a variable. You can reassign isintstring as long as you're not trying to declare it const, which includes method definitions.
julia> isintstring = str -> mapreduce(isnumeric, &, collect(str))
#5 (generic function with 1 method)
julia> typeof(isintstring)
var"#5#6"
julia> isintstring(str) = all(isdigit(c) for c in str)
ERROR: cannot define function isintstring; it already has a value
julia> isintstring = 1
1
It's far more readable to add methods to a named function, all you have to do is define another method using the const name, like isintstring(int, str) = blahblah().
It's actually possible to add methods to an anonymous function, but you have to do something like this: (::typeof(isintstring))(int, str) = blahblah(). The variable isintstring may not always exist, and the anonymous function can have other references such as func_array[3], in which case you'll have to write (::typeof(func_array[3]))(int, str) = blahblah(). I think you'll agree that a const name is far clearer.
Anonymous functions tend to be written as arguments in method calls like filter(x -> x%3==0, A) where the anonymous function only needs 1 method. In such a case, creating a const-named function would only bloat the function namespace and force a reader to jump around the code. In fact, do-blocks exist to allow people to write a multiple-line anonymous function as a first argument without bloating the method call.
Just like Gandhi said "My life is my message", Julia says "My code is my guide". Julia makes it very easy to inspect and explore standard and external library code, with #less, #edit, methods, etc. Guides for semantic style are rather hard to pin down (as opposed to those for syntactic style), and Python is rather the exception than the rule when it comes to the amount of documentation and emphasis surrounding this. However, reading through existing widely used code is a good way to get a feel for what the common style is.
Also, the Julialang Discourse is a more useful resource than search engines seem to give it credit for.
Now, for the question in your title, "using functional idioms" is a broad and vague descriptor - Julian style doesn't generally place high emphasis on avoiding mutations (except for performance reasons), for eg., and side effects aren't something rare and smelly. Higher order functions are pretty common, though explicit map/reduce are only one part of the arsenal of tools that includes broadcasting, generators, comprehensions, functions that implicitly do the mapping for you (sum(f, A::AbstractArray; dims): "Sum the results of calling function f on each element of an array over the given dimensions"), etc.
There's also another factor to consider: performance trumps (almost) anything else. As the other answers have hinted at, which style you go for can be a matter of optimizing for performance. Code that starts out reading functional can have parts of it start mutating its inputs, parts of it become for loops, etc., as and when necessary for performance. So it's not uncommon to see a mixture of these different style in the same package or even the same file.
they are the same. and if you just look at it...clearly the first one is cleaner even shorter

Using "where" syntax to parametrize a function in Julia [duplicate]

This question already has an answer here:
`where` in function definitions in julia-0.6
(1 answer)
Closed 5 years ago.
Reading the Julia documentation on parametric methods, I can't for the life of me figure out the difference between these two definitions
julia> function f{T<:Real}(x::T)
println("$x with type $T")
end
julia> function g(x::T) where {T<:Real}
println("$x with type $T")
end
Any guidance on the semantic difference between these two definitions would be highly appreciated.
The former is deprecated (in most instances) for the latter. where replaces the old syntax in v0.7 and onwards, and the first will not exist in 1.0.
One exception is inner constructors. The first syntax will still exist for them. But in that case type parameters means something very different. Example: Array{Float64,2}() the inner constructor takes in the parameters from the user. This was confusing before because type parameters had a dual meaning for these different constructs, but now this way of parameterizing only exists for inner constructors and only means this, whereas everything else uses where.

Vector as an exponent in Julia

I have very basic question. I am new to Julia and used to code in R a lot. I need to take a scalar to the multiple powers, represented by a vector: 3^[2,3]. I got an error "Method error: no method matching ^...". I tried 3^Array([2,3]), but got the error again. At the same time, 3*[2,3] works as expected. Is there any way to do it in Julia without using for loop?
I think you are looking for the . or broadcast functions that allow you to apply any other functions elementwise!
3 .^ [2,3] or broadcast(^, 3, [2,3])
Small edit: you'll need a space after the number to be exponentiated, e.g. 3 .^[2,3].

R expression results in NaN for no obvious reason [duplicate]

This question already has answers here:
How to calculate any negative number to the power of some fraction in R?
(2 answers)
Closed 6 years ago.
How can it be that the expression
> (exp(17.118708 + 4.491715 * -2)/-67.421587)^(-67.421587)
results in
[1] NaN
while
> -50.61828^(-67.421587)
which should basically have the same outcome, gives me
[1] -1.238487e-115
This is driving me crazy, I spent hours searching for the Error. "-2", in this case, is a Parameter of the function. I really can't think of a solution. Thanks for your help!
EDIT:
I see that when I add brackets
> (-50.61828)^(-67.421587)
it also results in
[1] NaN
...but that does not solve my Problem.
It is because of the implementation of pow under C99 standard.
Let alone OP's example: (-50.61828)^(-67.421587), the mathematically justified (-8)^(1/3) = -2 does not work in R:
(-8)^(1/3)
# [1] NaN
Quoted from ?"^":
Users are sometimes surprised by the value returned, for example
why ‘(-8)^(1/3)’ is ‘NaN’. For double inputs, R makes use of IEC
60559 arithmetic on all platforms, together with the C system
function ‘pow’ for the ‘^’ operator. The relevant standards
define the result in many corner cases. In particular, the result
in the example above is mandated by the C99 standard. On many
Unix-alike systems the command ‘man pow’ gives details of the
values in a large number of corner cases.
I am on Ubuntu LINUX, so can help get relevant part of man power printed here:
If x is a finite value less than 0, and y is a finite noninteger, a
domain error occurs, and a NaN is returned.
From what I can tell, -50.61828^(-67.421587) is evaluating as -(50.61828^(-67.421587)). (-50.61828)^(-67.421587) also results in NaN.

Equal numbers shown as false when compared in R [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
In R, what is the difference between these two?
floating point issue in R?
This is part of a code I created. I spend days looking for the problem when finally realized that a comparison that should be TRUE was being calculated by R as FALSE. I'm using R 2.14.2 64 bits on windows. This is the code to reproduce the problem.
concList= c(1.15, 1.15, 1.15 ,1.15 ,1.15 ,1.15 )
concList=concList-0.4
a=sum(concList)
b=length(concList)*0.75
str(a)
str(b)
print(a==b)
The last print will result in FALSE even thou they are shown as exactly the same number. I tough this could be some problem on the floating point numerical representation of R, so I added the code below which solves the problem.
a=round(a,1)
b=round(b,1)
print(a==b)
My question is, is there any more elegant solution? Is this a bug that should be reported?
Thanks for your time.
Because they aren't exactly the same number. They differ by a very small amount due to the computer's representation of numbers, also known as floating point errors:
> a - b
[1] -8.881784e-16
Jon Skeet has an excellent blog post on this issue, which pops up on Stack Overflow with some regularity.
As #mrdwab suggests in the comments, you should use all.equal(a, b) to test for near equality.

Resources