"Not a rational" constant?

In porting some C code I came across a value called NaR, which was defined as Not a Rational (when returned due to error from a function returning a rational). In terms of type consistency, is there a rational in Julia that would be equivalent to NaR?

I suppose 1//0 could be one, and this is what I am now using, but this becomes Inf when converted to float, and I’d prefer it convert to NaN, so that

(NaR isa Rational) == true 
float(NaR) == NaN

Rational{T} is a leaf type for each T so you can’t define your own elements in the type.

There’s no problem with making your own function. Something along the lines of

function finitefloat(x)
	f = float(x)
	return isfinite(f) ? f : oftype(f,NaN)
end

Note: changing how rationals interact with general functions without going through wrappers like this example is not something easy to do without the extremely dangerous and strongly discouraged act of type piracy (and even then, is only “easy” if it doesn’t accidentally break a bunch of other stuff you’re trying to use).

Theoretically NaN could map to 0//0, but that’s explicitly not allowed:

julia> 0//0
ERROR: ArgumentError: invalid rational: zero(Int64)//zero(Int64)

Instead, I’d probably return missing in situations like this and explicitly coalesce to NaN upon converting to float.

3 Likes

What is the reasoning here? Seems rather inconsistent to me.
Also I find the errors to be inconsistent:

0//0 # ArgumentError of constructor, explains zero/zero is invalid Rational
(1//0)*0 # DivideError in gcd, says division by 0 not allowed

The reasoning is basically just that allowing 1//0 and -1//0 as infinite values works out well in the math without adding extra checks while supporting 0//0 adds a special case to basically any function that deals with rationals.

2 Likes