Open maxale opened 2 weeks ago
It is worth to note that full_simplify()
does simplify q
into 1/514
:
sage: q.full_simplify()
1/514
while .is_real()
also produces a wrong result:
sage: q.is_real()
False
It's is_zero()
returning false here but…
def __bool__(self):
"""
Return ``True`` unless this symbolic expression can be shown by Sage
to be zero. Note that deciding if an expression is zero is
undecidable in general.
EXAMPLES::
sage: x = var('x')
sage: forget()
sage: bool(SR(0))
False
sage: bool(SR(1))
True
sage: assert(abs(x))
sage: assert(not x/x - 1)
This is called by :meth:`is_zero`::
sage: k = var('k')
sage: pol = 1/(k-1) - 1/k - 1/k/(k-1)
sage: pol.is_zero()
True
sage: f = sin(x)^2 + cos(x)^2 - 1
sage: f.is_zero()
True
Not sure if anything Sage can do here about it.
Reading: https://math.stackexchange.com/questions/617529/richardsons-theorem-for-constants/1379799#1379799
Not sure if anything Sage can do here about it.
Well, if is_zero
is unable to determine the answer for a given expression it should raise an exception to make the caller aware about the issue, but it should not return a wrong/uncertain answer.
I imagine that would be quite hard to implement while making Sage still reasonably useful in practice.
sage: y=(x+abs(x)+I)^2
sage: ((y^2-1)/(y+1)-y+1).is_zero()
True
sage: ((y^2-1)/(y+1)-y+1)(x=-3)
ValueError: power::eval(): division by zero
That said, the proposal that is_zero()
tries a bit harder for constant might be reasonable.
sage: q = -1/8224*2^(1/4)*(2^(3/4)*(64*(-1)^(3/4) - 7) + 17*I*2^(1/4)*((-1)^(3/4) - 4) - (-1)^(3/4)*
....: sqrt(193*sqrt(2) + 240*I) + 16*I*2^(3/4) + 60*2^(1/4))
sage: a = imag(q)
sage: a.variables()
()
The question is how much harder, however. N
is probably reasonably fast, but simplify()
can be arbitrarily slow.
The original example shows that q.imag().is_zero()
and q.is_real()
both give incorrect result. This may make an impression that the two are being somewhat equivalent, but it turns out that each of them may produce an incorrect result independently of the other.
In the following example r.imag().is_zero()
gives correct True
while r.is_real()
gives incorrect False
:
r = -1/2056*sqrt(2)*(-231043*sqrt(2) + 1682065/4)^(1/4)*cos(1/2*arctan(1/2*sqrt(-67260300684*sqrt(2) + 97845815881)/(38051*sqrt(2) + 20432)))
print( r.n() )
print( r.imag().is_zero() )
print( r.is_real() )
Output:
-0.0118652163874385 True False
I've separated the issue with .is_real()
to #38600. Let's devote this one to .is_zero()
.
Steps To Reproduce
The code:
prints:
Expected Behavior
Conversion to
QQbar
shows that the value ofq
is simply1/514
and thus its imaginary part equals 0.Actual Behavior
The call
imag(q).is_zero()
returnsFalse
, while the correct result should beTrue
. Hence, eitherimag()
oris_zero()
produces a wrong result here.Additional Information
No response
Environment
Checklist