Typeof(π+1) is not Irrational

I have not used irrational numbers in Julia so far and was surprised to discover that while π is indeed Irrational, π+1 is Float64. I would like to understand why.

1 Like

See Numbers · The Julia Language

In particular:

Number type representing an exact irrational value, which is automatically rounded to the correct precision in arithmetic operations with other numeric quantities.

The reason for this behavior is that you can’t really just add something to an irrational and keep the same genericness that the original type had (you could have a tape recording all operations, but that would slow down arithmetic tremendously). Internally, \pi etc. are defined in base/mathconstants.jl, with fairly high precision.

You may also be interested in this article from NASA, about how many digits of pi are actually required for (just about) all computations you’d usually be interested in:

5 Likes

Thanks for the explanation!

To be clear, they are defined to arbitrarily high precision. When you do arithmetic to combine π with some other quantity, it is replaced by a finite-precision approximation (typically determined at compile time) depending on the types of the other operands. e.g. π + 1 and 0.5π both evaluate π to double precision, but 0.5f0 * π evaluates π/2 to single precision.

The point of a special type for a constant like π, rather than simply defining it as a double-precision constant as in e.g. numpy or Matlab, is to allow you to write type-generic code (if you are careful). That is, you can write an expression like exp(-(π*x)) and it will work and use the full precision of x if x is single-precision, double-precision, BigFloat arbitrary precision, quad precision etcetera. (This requires careful attention to the parentheses, because the precision of π is determined by the first arithmetic operation you do on it.)

The same thing applies to rational constants. If you have a constant like 2/3 in your code, then it is evaluated in double precision (because that’s what / does with Int arguments), which would be bad if you want it to use a context-dependent precision. Instead, you can write the rational constant 2//3 and it will then be converted to the precision of whatever type you combine it with. (This conversion is done at compile-time in Julia 1.8, so rational constants are finally fast.)

10 Likes