Guys, this is serious. Any dev who starts reading this, give it a hard 
look, ok?

Below I give some examples where Sage give the wrong answer, with no error 
message or any indication that the answer is not correct.

Probably the single most important rule in software is, never ever give 
users the wrong answer.

Either give them the right answer, or give them no answer along with an 
error message explaining why the right answer can't be given.

Why the heck is Sage not following this rule?

After finding these examples, it's hard for me to trust any answer I get 
from Sage, unless I check it against other software, like Wolfram Alpha.

One possible response to my examples below is, I am not using Sage 
functions in an approved way.

But that's not a valid objection. A user should be able to send any 
argument to a function, and it's the responsibility of the programmer to 
make sure one of two things happen:

(a) the user is given the right answer;
or (b) the user is given no answer and an error message.

Sage is failing to do this.

On to the examples.

Example 1, straight from the sage RealField docs:

RealField(120)(RR(13/10))
1.3000000000000000444089209850062616

RR has default 53 bits, so this is really:

RealField(120)(RealField(53)(13/10))

Here's the same thing with less precision to make it clear that this has 
nothing to do with Python's single or double precision floats:

RealField(18)(RealField(12)(13/10))                     (A)

What should happen here is this:
RealField(12) should eval 13/10 as 1.30
RealField(12) should pass to RealField(18) only those digits, 1.30
RealField(18) should then zero-pad that to 18 bits, yielding 1.3000

Here's what sage does:

RealField(18)(RealField(12)(13/10))
1.2998

Let's check the types of all args:

type(13/10)
sage.rings.rational.Rational

type(18)    # type(12) is the same
sage.rings.integer.Integer

All args to RealField in (A) are Sage types. 
Hence everything in the calculation (A) is under the complete control of 
Sage.
Hence Sage could easily do the right thing here. 

But it doesn't.

You might say, this is an artificial example, passing the output of one 
RealField to another in a non-sanctioned way. 
Ok then, let's just pass arguments to one RealField. 
Can we get it to give wrong answers?

Yes, very easily, by passing it an arithmetic expression.

Sending in arithmetic expressions should be totally fine, because the 
RealField docs say: "This is a binding for the MPFR arbitrary-precision 
floating point library."

The purpose of MPFR is to be able to do basic arithmetic in arbitrary 
precision.
Basic arithmetic means any expression using the following ops (and maybe 
some others): +, -, *, /, ^  

So let's pass an arithmetic expression to RealField.
The whole point of MPFR is to always give the right answer for the value of 
such an expression, for any expression and any requested precision.
The docs say RealField is a binding for MPFR.
So RealField should only give right answers.
But in fact it sometimes gives the wrong answer.

Here's one:

RealField(200)(2*1.1)
2.2000000000000001776356839400250464677810668945312500000000

Let's check the types:

type(2)
<class 'sage.rings.integer.Integer'>

type(1.1)
<class 'sage.rings.real_mpfr.RealLiteral'>

type(2*1.1)
<class 'sage.rings.real_mpfr.RealNumber'>

Here the expression 2*1.1 is not only a Sage type, it's a Sage type 
designed to work with MPFR. Hence passing 2*1.1 to RealField should yield 
the right answer.

But it doesn't.

How the heck was this not noticed earlier?

I think I have a workaround for expressions such as 2*1.1: enter the 1.1 as 
a sage rational, 11/10:

RealField(200)(2*11/10)
2.2000000000000000000000000000000000000000000000000000000000

That works for this expression, but I worry that with other kinds of 
expression I could still get wrong answers.

By the way, in this example i used numbers where we know the answer in 
advance, so it's easy to see that the answer given is wrong.

Here's a very similar example where we don't know the answer in advance:

RealField(200)(e^(1.1))
3.0041660239464333947978502692421898245811462402343750000000

RealField(200)(e^(11/10))
3.0041660239464331120584079535886723932826810260162727621298

Wolfram Alpha says the second one is correct.

Let's check the types for the wrong one:

type(e)
<class 'sage.symbolic.constants_c.E'>

type(1.1)
<class 'sage.rings.real_mpfr.RealLiteral'>

type(e^(1.1))
<class 'sage.rings.real_mpfr.RealNumber'>

All are sage types, and the expression as a whole is a sage type designed 
to work with MPFR. Sage should give the right answer here, but it doesn't.

I like the idea of Sage. And I know the Sage devs must be solid 
professionals. But giving users junk answers makes Sage look bush-league.

The MPFR devs would never allow their library to give a junk answer.

Wolfram would never allow Mathematica or Alpha to give a junk answer.

Why the heck are the Sage devs allowing Sage to give junk answers?

-aw


-- 
You received this message because you are subscribed to the Google Groups 
"sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sage-devel+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sage-devel/83acb2d5-5210-4151-b5a1-826cdd6a6d05n%40googlegroups.com.

Reply via email to