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.