Hi,

I think the current way of representing Floats is reasonable.

Float internally keeps it in binary representation, so any non-terminating
number in base 2 is truncated when stored as a Float. That's why there is a
string constructor which can take in an exact decimal value and create a
number in binary representation with precision mentioned.

Note that in this way only numbers representable as a sum of different
powers of two have an exact value. Others can also be represented in an
exact form if the base of the float is different than 2, but I think mpmath
and many other libraries use only base 2.

If you want an exact form, best way would be to define it as a Rational and
then you can do 1/3 as well which you can't if it's in decimal form. One
other good thing about Rational is that `sin(Rational)` won't be evaluated
unless SymPy knows the exact value, whereas `sin(Float)` would evaluate
leading to error propagation even if it's something like `0.5` which
represented exactly in binary representation.

Isuru Fernando

On Tue, Apr 5, 2016 at 10:38 PM, Aaron Meurer <[email protected]> wrote:

> 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.
>

-- 
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/CA%2B01voO7R-t6hwL%3DLMF9RoZ2-G68SmpBZdV8k2zQgFb_U4TEoQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to