On Tue, Apr 5, 2016 at 12:54 PM, Oscar Benjamin
<[email protected]> wrote:
> On 5 April 2016 at 17:15, Aaron Meurer <[email protected]> wrote:
>> On Tue, Apr 5, 2016 at 6:19 AM, Oscar Benjamin
>> <[email protected]> wrote:
>>>
>>> I though that it should be possible to easily do this with sympy
>>> Floats but it doesn't seem to work:
>>>
>>> In [1]: x = S(1.4142)
>>>
>>> In [2]: x
>>> Out[2]: 1.41420000000000
>>>
>>> In [3]: x**6000
>>> Out[3]: 1.16144178843571e+903
>>>
>>> In [4]: x**6000 % 400
>>> Out[4]: 32.0000000000000
>>>
>>> This doesn't work because auto-evaluation of x**6000 destroyed all the
>>> precision so I tried:
>>
>> No, it's because the default precision is 15. I didn't realize you
>> needed a precision of 950. If you do what I did above with that you
>> get the right answer
>>
>> In [6]: x = Float("1.4142", 950)
> ...
>
> It is because of the auto-evaluation in the sense that there were
> enough digits to exactly represent all the input numbers but the
> auto-evaluation cheated me from specifying how many digits to use for
> the exponentiation with evalf later. I think that inexact
> auto-evaluation should be disabled by default. Explicitly calling
> .evalf() serves as a useful reminder of the numeric approximations
> that have occurred in the calculation and should be required for this.
>
>>> So let's disable evaluation of at the mod step as well:
>>>
>>> In [10]: Mod(Pow(x, 6000, evaluate=False), 400, evaluate=False).evalf(50)
>>> Out[10]:
>>>    ⎛      6000     ⎞
>>> Mod⎝1.4142    , 400⎠
>>>
>>> How do I get that to actually evaluate?
>>
>> expr.doit() will evaluate the expression, but it evaluates it using
>> the prevision of x. For your x, that's 15, so you get the wrong answer
>> 32. If you set x = Float("1.4142", 950) you get the right answer.
>
> Is there a reason for not evaluating this when evalf is called?

No, that's also a bug. Unevaluated objects in SymPy tend to be pretty buggy.

>
> ...
>>
>> I don't know if it should be considered a bug, but it's worth noting
>> that if you want SymPy to give the right precision in general you have
>> to start with Float objects that are set with the precision you need.
>> To me it feels like a bug because it negates the purpose of the evalf
>> precision argument.
>
> Is there a coherent policy on float-handling in sympy?
>
> My ideal would be:
>
> 1) All float objects are created exact (having the exact value of the
> object passed in).
> 2) No inexact auto-evaluation.
> 3) .evalf() can be used to fully evaluate the expression with desired 
> precision.
> 4) Ideally the precision argument to .evalf would be the precision of
> the *output* rather than the internal precision of the intermediate
> calculations

Can you clarify what you mean by "exact" here?

Note that there's no way to know what the input value of a float is.
That is, there's no way to write Float(0.2) (with no quotes) and have
it be treated as Float(2/10).  The 0.2 object is converted to a Python
floating point by the time that Float sees it, and it's not a decimal:

In [49]: (0.2).as_integer_ratio()
Out[49]: (3602879701896397, 18014398509481984)

That's why Float allows string input (and it's the recommended way of
creating them).

With that being said, I don't think the fact that
(1.4142).as_integer_ratio() isn't (7071, 5000) is the problem here.
Float(1.4142) is indeed inexact compared to Float('1.4142'), but the
wrong answers from x**6000%400 come from lack of computing precision,
not lack of input accuracy.

>
> Currently 1) already occurs for decimal strings but Float(float)
> rounds to 15 digits and you can explicitly force something impossible
> as a ratio string: Float("1/3"). I think Float should be more like
> decimal.Decimal here: all input arguments are treated as exact
> regardless of precision etc. (and I don't see any good reason for
> allowing Float("1/3"))
>
> Without 2) it is impossible to achieve 3). If approximate
> auto-evaluation can occur before calling .evalf then there's no way
> for evalf to set the precision to be used for the auto-evaluation.
>
> Obviously 4) is harder than current behaviour and perhaps impossible
> in general but it is achievable for simple cases like in this thread.
> From a user perspective it is definitely what is actually wanted and
> much easier to understand.

I'm unclear how this works, because if you take my example above with
x = nsimplify("1.4142"), evalf() gave the right answer with the
default precision (15). That is, when everything in the expression is
a non-float, it gives the right answer. However, it seems that as soon
as an expression contains a Float, that Float must have whatever
precision you need set on it.

My knowledge of how this works internally is rather limited. Most of
what I know is based on my observations on how things work. I've CC'd
Fredrik Johansson. Hopefully he can give better insight into how
things should be working here.

Aaron Meurer

>
> --
> Oscar
>
> --
> You received this message because you are subscribed to the Google Groups 
> "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at https://groups.google.com/group/sympy.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sympy/CAHVvXxRxmU9wrh__88Jw0ERkht3BPzFjo_cu3_iuvRdJdy_BrA%40mail.gmail.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sympy.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sympy/CAKgW%3D6KhqcKoJgoK013m%2BotSRa1cAC%3DOxmtPVh%2B_6C_jGHbmzw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to