Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to tell Julia to interpret 0.0/0.0 as 1?

Tags:

julia

I'm dealing with some Float64 functions that inside its body compute some fractions that can take the value 0.0/0.0. In that case, that value should be interpret as 1.0. Is it possible to do this automatically and avoid coding the pathological cases?

like image 392
Gonzalo Benavides Avatar asked Sep 20 '19 01:09

Gonzalo Benavides


1 Answers

Yes, it is fairly straightforward to do this in a safe way that doesn't break julia or other people's code.

One way to achieve this is either inside your module or at the REPL, before you ever explicitly use the / function[1], simply write

/(args...) = Base.:(/)(args...)

function /(x::Float64, y::Float64)
    if x == 0.0 && y == 0.0
        1.0
    else
        Base.:(/)(x, y)
    end 
end

At the repl:

julia> 1 / 2
0.5

julia> 10.0 / 0.0
Inf

julia> 0.0 / 0.0
1.0

What this does is shadows the built in / function and replaces it with your own custom version that falls back on the built-in one. This shadowing is local to only the current module you're in and won't leak outside unless someone explicitly asks for your version.

Another (perhaps preferable) option is to make a new infix division function via unicode operators. Here's an example:

function /̂(x, y) # /̂ is typed /\hat<TAB> at the REPL
    if x == 0 && y == 0
        one(promote_type(typeof(x), typeof(y)))
    else
        x / y
    end 
end

At the REPL:

julia> 0 /̂ 0.0
1.0

julia> 1 /̂ 2
0.5

julia> 0 / 0
NaN

This works because anytime you apply a unicode modifier like \hat or a superscript or whatever to an infix function symbol (like / or * or whatever) you make a new infix operator with the same precedence. This is nice because we get to keep the old / definition around and we have a visual marker on our division operator that something peculiar is happening.

Enjoy!


[1]: Functions from Base are only actually pulled into your namespace the first time you use them, so if you have not yet used / in your current scope, you are free to shadow it. Otherwise, you'll have to introduce a new scope via a let block and only have / shadowed there.

like image 96
Mason Avatar answered Nov 15 '22 23:11

Mason