Make Unitful simplify expressions like 1μm/1m to a unitless value by default

I freguently perform computations like 1μm/1m and would like Unitful to return a unitless number by default rather than having to do NoUnits(1μm/1m).

Is there a setting to make this the default?

I’m not sure you can set a default, but FWIW, you might not need to, e.g.:

julia> using Unitful: μm, m

julia> 1μm/1m + 0
1.0e-6

For this purpose, I’m using a small piece of code listed below. It allows me to use for example // as a unit stripping operator.

After including the code below, I can just define the unit stripping operator and use it in a pretty readable way - this way I keep variables tagged with units as long as possible and strip the units just before printing or plotting, so I know exactly if I’m plotting in ns, microseconds or seconds

julia> @stripunits_operator //
julia> u = 15u"V"; d = 5u"mm"; E = u/d
julia> println("The field intensity is \$(E // u"V/m") [V/m] in a gap of \$(d // u"m") [m]")
The field intensity is 3000.0 [V/m] in a gap of 0.005 [m]

julia> typeof(E // u"V/m")
Float64

The code to include:

function stripunits(a::Unitful.Quantity, u::Unitful.Units)
    try
        return _stripunits(a,u)
    catch
       throw(ArgumentError("Cannot convert $a / $u to a Float64"))
    end
end

function _stripunits(a::Unitful.Quantity{T,D,UA}, u::Unitful.Units{UU,D}) where {T, D, UA,  UU}
    return a.val * Float64(Unitful.convfact(u, UA()))
end

macro stripunits_operator(op)
    blk = quote
        import Base.$op
        function Base.$op(a::Unitful.Quantity{T,D,UA}, u::Unitful.Units{UU,D}) where {T, D, UA,  UU}
            _stripunits(a, u)
        end
    end
    push!(blk.args, :nothing)
    blk.head = :toplevel
    return blk
end

Would a “unit simplification” function be useful? For example, something like:

usimplify(x) = typeof(dimension(x)) == Unitful.Dimensions{()} ? ustrip(x) : x

I like

x |> upreferred

If it’s unitless, that will strip units. If it’s united it will make it SI. Very useful.

Perhaps, one thing that might be annoying about upreferred is the zeal it can have with accuracy:

3u"μm" |> upreferred

3//1000000 m

You could overload show for Unitful Quantity to perform the simplification before printing the value to the terminal or otherwise displaying it.

You can solve this easily:

float(3u"μm" |> upreferred)

3.0e-6 m

3u"μm" |> upreferred |> float if you don’t want to mix styles.

Exact conversions between units are respected where possible. If rational arithmetic would result in an overflow, then floating-point conversion should proceed. Use of floating-point numbers inhibits exact conversion.

julia> 3.0u"μm" |> upreferred
3.0e-6 m

I saw this thread after I posed my new version announcement for FlexUnits.jl which includes this feature. It simplifies units better than upreferred which can give you rather opaque results with a lot of electrical units. You can even use display_simplified_units(true) to set it to simplify units by default when displaying.

FlexUnits.jl follows much of Unitful’s convention so it shouldn’t be too difficult for most people to pick up. It matches Unitful for speed in statically inferrable cases, but absolutely dominates Unitful for cases where units can’t be inferred (this bothered me a lot because I often build configurable systems where I have to parse units as string, which completely wrecks performance, FlexUnits solves that problem with Unitful as well as many others).