This package exports the type PiExpTimes that satisfies PiExpTimes(x, n) = x*π^n. It also provides the constant Pi for convenience, defined as PiExpTimes(1, 1), that behaves like π except it produces results with higher accuracy in certain trigonometric and algebraic contexts. In most scenarios the numbers Pi and π are interchangable. Expressing mathematical relations in terms of Pi instead of the more cumbersome PiExpTimes is usually cleaner, and is recommended unless it's specifically necessary to do otherwise.
The number π is represented as an Irrational type in julia, and may be computed to an arbitrary degree of precision. In normal course of events it is converted to a float when it encounters another number, for example 2π is computed by converting both 2 and π to floats and subsequently carrying out a floating-point multiplication. This is lossy, as both 2 and π may be represented with arbitrary precision. This package delays the conversion of the π to a float, treating it as a common factor in algebraic simplifications. This limits floating-point inaccuracies, especially if the terms multiplying π are exactly representable in binary. As an added advantage, it uses sinpi and cospi wherever possible to avoid having to convert π to a float altogether.
Delaying the conversion of π to a float results in precise mathematical expressions such as
Using π | Using Pi |
|---|---|
julia> (1//3)π + (4//3)π == (5//3)π
false
julia> float(sqrt(pi)^2) == float(pi)
false |
julia> (1//3)Pi + (4//3)Pi == (5//3)Pi
true
julia> float(sqrt(Pi)^2) == float(Pi)
true |
We may also simplify algebraic expressions involving powers of Pi as
julia> (2Pi^2//3) // (4Pi//5)
(5//6)Pi
julia> Pi^-2 / 4Pi^3
0.25*Pi^-5Expressions involving Pi are automatically promoted to Complex as necessary, eg.
julia> (1+im)Pi^3 / 2Pi^2
0.5*Pi + 0.5*Pi*im
julia> (1+im)Pi^3 / 2Pi^2 * 2/Pi
Pi^0 + Pi^0*imThe type PiTimes uses sinpi and cospi under the hood when it is used as an argument to sin and cos. This results in exact results in several contexts where the inaccuracies arise from floating-point conversions.
Using π | Using Pi |
|---|---|
julia> cos(3π/2)
-1.8369701987210297e-16
julia> sin(-π)
-1.2246467991473532e-16
julia> tan(π/2)
1.633123935319537e16 |
julia> cos(3Pi/2)
0.0
julia> sin(-Pi)
-0.0
julia> tan(Pi/2)
Inf |
We may compute complex exponential exactly:
Using π | Using Pi |
|---|---|
julia> exp(im*π/2)
6.123233995736766e-17 + 1.0im
# Euler's identity : exp(iπ) + 1 == 0
julia> exp(im*π) + 1
0.0 + 1.2246467991473532e-16im |
julia> exp(im*Pi/2)
0.0 + 1.0im
# Euler's identity : exp(iπ) + 1 == 0
julia> exp(im*Pi) + 1
0.0 + 0.0im |
Hyperbolic functions work as expected:
Using π | Using Pi |
|---|---|
# cosh(ix) = cos(x)
# Should be exactly zero for x = π/2
julia> cosh(im*π/2)
6.123233995736766e-17 + 0.0im |
# cosh(ix) = cos(x)
# Should be exactly zero for x = π/2
julia> cosh(im*Pi/2)
0.0 + 0.0im |
The irrational number π is usually aggressively converted to Pi, eg:
julia> π * Pi
Pi^2This ensures that subsequent calculation would not get promoted to a floating-point type. However if this behavior is not desired then one may specify the type explicitly while constructing the object as
julia> PiExpTimes{Irrational{:π}}(π)
π*Pi^0Addition and subtraction involving mixed exponents of Pi will involve floating-point conversions, and the resulting expression will have the minimum exponent out of the terms being summed.
julia> Pi + 3Pi
4Pi
julia> Pi + 3Pi^2
10.42477796076938*PiThis fits with the intuition of the expression being factorized as Pi + 3Pi^2 == Pi*(1 + 3Pi).
Note that π is promoted to Pi in such operations, so we obtain
julia> Pi + π
2PiNote that addition and subtraction are not type-stable at present by design.
In general using Pi instead of pi will be less performant, as pi is aggressively promoted to a floating-point value in most calculations. The use of Pi is mainly intended for tests where exact fractions of Pi are desirable.
Install the package using
pkg> add MultiplesOfPi