是否可以告诉Julia将0.0 / 0.0解释为1?

Gon*_*des 8 julia

我正在处理一些Float64函数,这些函数在其主体内部计算可以取值0.0 / 0.0的某些分数。在这种情况下,该值应解释为1.0。是否可以自动执行此操作并避免对病理病例进行编码?

Mas*_*son 11

是的,以安全的方式做到这一点非常简单,不会破坏julia或其他人的代码。

实现此目的的一种方法是在模块内部或REPL处,在显式使用/function [1]之前,只需编写

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

function /(x::Float64, y::Float64)
    if x == 0.0 && y == 0.0
        1.0
    else
        Base.:(/)(x, y)
    end 
end
Run Code Online (Sandbox Code Playgroud)

在代表:

julia> 1 / 2
0.5

julia> 10.0 / 0.0
Inf

julia> 0.0 / 0.0
1.0
Run Code Online (Sandbox Code Playgroud)

它的作用是隐藏内置/函数,并用您自己的自定义版本替换内置函数,而该自定义版本将落在内置函数上。这种阴影仅存在于您所在的当前模块中,并且不会泄漏到外部,除非有人明确要求您提供版本。

另一个(也许是更可取的)选择是通过unicode运算符创建一个新的中缀分割函数。这是一个例子:

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
Run Code Online (Sandbox Code Playgroud)

在REPL:

julia> 0 /? 0.0
1.0

julia> 1 /? 2
0.5

julia> 0 / 0
NaN
Run Code Online (Sandbox Code Playgroud)

之所以有效,是因为只要您将unicode修饰符(例如\hat或上标)或其他内容应用到中缀函数符号(例如/*或其他)上,便会创建一个具有相同优先级的新infix运算符。这很好,因为我们可以保留旧的/定义,并且在除法运算符上有一个可视标记,表明正在发生某些特殊情况。

请享用!


[1]:来自Base的函数实际上只是在您第一次使用它们时才被拉到您的命名空间中,因此,如果尚未/在当前作用域中使用它,则可以随意对其进行阴影处理。否则,您将不得不通过一个let块引入一个新的作用域,并且只在/此处添加阴影。

  • 不,不是。正如这里定义的,“ /”是一个全新的函数,有时称为“ Base.:(/)”。正如梅森所说,它不会“泄漏”到其他模块中。 (6认同)
  • 可能要提及的是,如果已经将Base.:(/)纳入了范围,那么您将无法全局执行此操作,但是仍然可以使用let块来执行此操作。 (2认同)