Complexifying pi

In general you shouldn’t use Complex, that’s the type, it’s easier to use the constructor complex. Complex could be useful only in the case in which you want to force the parameter:

julia> Complex{Float64}(3, -2)
3.0 - 2.0im

In any other case, go with complex. float converts the number to the most appropriate “floating-point number”, but there is no Float type associated. Note: as convention, in Julia type names starts with capital letter, while function names are all lower case.

Well, in Julia there is no Irrational 2pi :wink: However there is tau from GitHub - JuliaMath/Tau.jl: A Julia module providing the definition of the circle constant Tau (2π) which serves that goal

Yes, that’s exactly the point. Given their nature, irrational numbers can’t be represented numerically by a finite-memory computer, so anyway you end up with a float number with any operations you do. Julia doesn’t do symbolic algebra. Just keep in mind this. The convenience of the Irrational type in Julia is that they’re automatically converted to the most appropriate precision the first time they get in contact with another number:

julia> pi * 1
3.141592653589793

julia> pi * big(1)
3.141592653589793238462643383279502884197169399375105820974944592307816406286198

You can check the second one has the correct expansion of pi (the very last digit may be wrong), instead the first one is precise up to the 53-bit significand of a Float64, in fact

julia> big(pi * 1)
3.141592653589793115997963468544185161590576171875

gets soon wrong after the 16-ish significant digit

In that case you should consider to treat irrational numbers in a special way: either do float(x) (effectively convert to Float64), or big(x) in case you want the maximum precision possible or do something else. In case your function has another argument, consider using a promotion rule.

1 Like

Since Julia has many float types (and users can define new ones), providing a value of \pi in all of them makes sense. One could imagine an interface like

get_π(::Type{T}) where {T <: AbstractFloat} = ...

The Irrational type provides an analogous solution: in most cases

op(π, x::T)

is equivalent to

op(get_π(T), x)

ie the type is resolved on demand.

Of course the analogy breaks when there is no other type that can be used to resolve the desired type. Nevertheless, it is still a neat interface when you think about it.

I don’t see why there would ever be a reason to convert π to a Complex.

The original post mentions "a type that internally stores values in a Complex form, but if this type is concrete (e.g. Complex{Float64}) then it will already work, and if it is not concrete, then why not use Number instead of Complex?

Related to this discussion: I just noticed that imag(pi) throws the exact same error as the one in the original post. (This happens in every Julia version that I have installed, including the latest nightly.)

I will file an issue on github, unless there is one already.

There is
https://github.com/JuliaLang/julia/issues/22878
for complex(pi)

Edit: I see what you mean, imag(pi) should be easy to define.

2 Likes