IrrationalExpressions is a Julia module that makes expressions like
2π behave as irrational numbers, rather than
Julia has a few irrational constants, like
e. Arbitrary precision packages, like BigFloat, may provide conversion methods that yield these constants with the desired precision. However, any arithmetic operation that happens before conversion defaults to
julia> BigFloat(π) + BigFloat(-π) 1.224646799147353177226065932275001058209749445923078164062861980294536250318213e-16 julia> typeof(-π) Float64
This may lead to subtle bugs. For example,
2π*x will only be correct to about 16 decimal places, even if
x has higher precision. It must be written as
2(π*x) in order to get the precision of
IrrationalExpressions module, arithmetic operations don't immediately force conversion to Float64. Instead the expression is kept unevaluated until the target type is known.
julia> using IrrationalExpressions julia> -pi -π = -3.1415926535897... julia> BigFloat(π) + BigFloat(-π) 0.0
/ are currently supported.
Downconversion occurs when a floating point value is encountered. The resulting type is that of the floating point value.
julia> τ = 2π 2π = 6.2831853071795... julia> τ + 0.0 6.283185307179586 julia> τ + BigFloat(0) 6.283185307179586476925286766559005768394338798750211641949889184615632812572396
Base typically convert to
Float64 when encountering an unknown subtype of
Real. They will work as usual.
julia> cos(2π) 1.0 julia> typeof(ans) Float64
Irrational can be used to build irrational expressions.
Care must be taken so that floats are not accidentally created.
(1//2)π is an
(1/2)π is a
New floating-point types need not explicitly support conversion from
Any subtype of
AbstractFloat that has conversions from
Irrational, promotion from
Real and the necessary arithmetic operations is automatically supported.
Because this is a quick hack, there's no simplification, or elimination of common subexpressions. If irrational expressions are inadvertently created in a loop, they can grow exponentially
julia> a = π; for i=1:5; global a = a-a/3; end; a ((((π - π / 3) - (π - π / 3) / 3) - ((π - π / 3) - (π - π / 3) / 3) / 3) - (((π - π / 3) - (π - π / 3) / 3) - ((π - π / 3) - (π - π / 3) / 3) / 3) / 3) - ((((π - π / 3) - (π - π / 3) / 3) - ((π - π / 3) - (π - π / 3) / 3) / 3) - (((π - π / 3) - (π - π / 3) / 3) - ((π - π / 3) - (π - π / 3) / 3) / 3) / 3) / 3 = 0.41370767454680...
(The work-around is to convert to the desired floating-point type before entering the loop.)
- There needs to be some way to keep expressions from blowing up in a loop. At minimum, the size should be tracked, and an error thrown at some point.
- It would be possible to extend this to things like
- Support for complex-valued irrational expressions, like
pi * imis still missing.