Extending Float64 Base.show

Dear julia experts—I would like to print very small numbers in terms of eps(Float64). Something like

julia> Base.show(io::IO, p::Float64) =
          print(io, (abs(p)<1000*eps(Float64)) ? sprintf("%.3feps", (p/eps(Float64))) : p)

This runs into a “minor” difficulty, of course. I have overridden the original Base.show. I need to rescue it first.

An even more minor issue is that I would like to have it work later under 0.7 and 1.0, too. will it still work the same?

Just define your own printsmall(x) function; you generally shouldn’t overwrite Base methods on Base types.

Note that print by default calls show, so writing show(x) in terms of print(x) as you have done here will probably lead to a dispatch loop.

hi steven: yes, I know that the final term does cause the fatal loop. this is what I need to avoid.

but I also want to do this, because there is an advantage for overriding Base.show(). Even if Float64 then appear in vectors or structs, they still display how I want them to display.

Realize that by changing Float64 display your code may not be composable with other code that relies on the Base behavior, which is a big drawback.

One way to change the display of Base types without composability problems (i.e., without type piracy) would be to define your own struct MyIO <: IO; io::IO; end type wrapping another io stream, and then define your own Base.show(io::MyIO, x) methods, falling back to Base.show(io::MyIO, x) = show(io.io, x). You can even redirect stdout to go to a MyIO stream.

That being said, if you really want to do this you need to look at what Base.show(io, x::Float64) normally calls. Currently, it is a method on Union{Float32,Float64}, so by defining your own show(io, ::Float64) you are just providing a more specific method, not overwriting the existing method. Therefore, you can call the old method by using invoke.

4 Likes

in case someone else ever needs this, the file is .../julia/base/grisu/grisu.jl

function Base.show(io::IO, x::Union{Float64,Float32})
    if get(io, :compact, false)
        _show(io, x, PRECISION, 6, true, true)
    else
        _show(io, x, SHORTEST, 0, true, false)
    end
end