I think that this result is not correct. According to the docs, zero(T::Type) and one(T::Type) return the additive and multiplicative identities for T, respectively. But in this case that’s not true:
julia> Base.:+(x::Bool, y::Irrational) = x ? 1 + y : y
julia> false + π === π
true
to make Irrationals behave a little better.
But that’s the problem with Irrational, there’s always something that could be improved a little bit. Maybe you want a specialized method to make sin(π) return 0 instead of 1.2246467991473532e-16? That’s easy to add as well. What about sin(2π), maybe not as easy but doable with some more type tricks. Continuing along this road leads you to a full blown Computer Algebra System, which would be completely unrealistic to build into Julia Base.
That’s interesting, is that a warning, or is this wanted?
Is that from some (older?) Julia version? Julia 1.8.1 (for me, and should for all, I believe no portability issue) DOES return 0.0 exactly (I think they tried reall hard for that to happen unlike for other multiples of π). But not for bitstring(sin(2π)), nor even sin(-π), does for sin(0) though. There’s a reason for sinpi.
then there’s an argument that either this should be fixed, or methods for one and zero should be removed.
There may be a blurry line somewhere between what should be included and what shouldn’t, but I don’t think that line should lie between the existence of zero(::AbstractIrrational) and the correct behavior of zero(π) + π.
I don’t have a strong opinion on the line for irrationals, but I suspect that removing zero and one would break a lot of things in the presence of irrationals.
Yes, but I thought the polynominal might have been changed, but apparently not:
julia> sin(Float64(π))
1.2246467991473532e-16
So just making sure for:
Base.sin(::Irrational{:π}) = 0.0
Base.cos(::Irrational{:π}) = -1.0
Base.sincos(::Irrational{:π}) = (0.0, -1.0)
Base.tan(::Irrational{:π}) = 0.0
Base.cot(::Irrational{:π}) = -1/0
unlike for:
julia> cos(Float64(π)) #even exact with: bitstring(cos(Float16(π)))
-1.0
julia> typeof(-π) # so not possible for it currently (or would there have been some possible workaround to get sin(-π) exact?)
Float64
I think 2π (as a literal constant) could have been changed to a separate “2π” irrational, and made exact, maybe not good under that name, since variables/constants cant start with number, rather twopi, or simply tau. I think they simply (wisely) chose to not do it in Julia, since can be done in a package; it was maybe a mistake to include any irrationals in Julia, this is a can of worms, and Julia itself doesn’t need them.
Unary minus on irrationals could also have been defined on irrationals, to give their mirrors, and then you have at least 4 pi-related irrationals. At some point it will be surprising, e.g. that 3π or simply 2.0π. So you would have to multiply again by 2 (at least), the number of irrational types, to support float (well Float64 only).
Naturally, removing one and zero is not an option. But handling *(::Bool, ::AbstractIrrational), etc., seems like a decent possibility, despite the ‘slippery slope’ argument (I actually think the slippery part lies between those two options). Unless, of course, that too would break stuff.
Thanks for the Knuth reference (just adds one more obscure trivia you need to know for [IEEE] floating point; not sure it applies to Post floating point, and its NaR).
Since false as “strong zero” is meant to disable propagation of NaN, when intended, explicitly used, is it then a bug related to irrationals (false and true, had other reasons for them there, related to Float64 or no other type good enough), to silently disable NaN propagation (which is a good thing, except when you want to turn it off)?
julia> faraway_calculation_results_in = NaN
julia> faraway_calculation_results_in*zero(π) # not sure how often this, or similar, would be done in practice though.
0.0
unlike:
julia> faraway_calculation_results_in*zero(Float64(π))
NaN
[File a (separate) bug? Or is it simply a known issue, part of the other open bug linked from this thread?]
This might have to do with it (didn’t look into it carefully):
No, or this is tricky, where is the bug? one(π) == true (meaning “1”) IS the multiplicative identity of π, just regular math).
The “bug” if you will then happens with true * π no longer being an irrational (also for false). That (and for false) seemingly could be fixed, but not for true + π (while false + π could be made to work).
julia> one(π) * π ≉ π # EDIT: !(one(π) * π ≈ π) # I didn't locate an \notapprox operator, is there one?
false
I think these issues come down to two basic issues:
Comparing real numbers for equality is undecidable
Implementing a CAS is not in scope for Julia Base
Perhaps Irrational shouldn’t ever have been a type, instead a better design (given the above limitations and expectations of consistency with the rest of Julia) might have been to make each irrational constant a function that takes a <:Real type.
Something like this: