On Tue, Apr 5, 2016 at 6:19 AM, Oscar Benjamin
<[email protected]> wrote:
> On 5 April 2016 at 01:56, Amy Valhausen <[email protected]> wrote:
>>
>> import numpy
>> (np.longdouble(1.4142)** 6000 )%400
> ...
>>
>> # The library mpmath is a good solution
>>>>> import sympy as smp
>>>>> mp = smp.mpmath
>>
>>>>> mp.mp.dps = 50 # Computation precision is 50 digits
>
>
> 50 digits is nowhere near enough. Think about what the number
> 1.4142**6000 is: it's a big number. If I wrote it out in digits it
> might look something like:
>
> 5432321453425234...234234234.123235345345
>
> The digits that contain the precision needed to get the remainder
> modulo 400 begin just before the decimal point. So how many digits are
> there before that? If d is the number of digits preceding the decimal
> point then loosely:
>
> 10**d = 1.4142**6000
>
> Which gives that
>
> d = log10(1.4142**6000) = 6000*log10(1.4142) ~= 903
>
> So if you want an answer that's good for m digits you'll need to use
> about 900+m digits for the exponentiation:
>
> In [1]: from sympy import mpmath
>
> In [2]: mpmath.mp.dps = 950
>
> In [3]: mpmath.mpf('1.4142') ** 6000 % 400
> Out[3]:
> mpf('271.048181008630921815939109488389292518324580362344398848121124779167483584534976647550313880646779627157871790825164801629065802757168057723902165889739990234375')
>
> BTW it's also possible to do this particular calculation easily enough
> just with Python stdlib (and without numpy or sympy):
>
> In [1]: from fractions import Fraction
>
> In [2]: float(Fraction('1.4142')**6000 % 400)
> Out[2]: 271.04818100863093
>
>
> 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)
In [7]: x**6000%400
Out[7]:
271.04818100863092181593910948838929251832458036234439884812112477916748358453497664755031388064677962715787179082516480162906580275716805772390216588973999
023437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000
>
> In [5]: Pow(x, 6000, evaluate=False)
> Out[5]:
> 6000
> 1.4142
>
> In [6]: Pow(x, 6000, evaluate=False) % 400
> Out[6]: Mod(1.16144178843571e+903, 400)
>
> Well that's annoying. It's gone ahead and auto-evaluated the x**6000
> but created a Mod object instead of evaluating the modular division.
>
> 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.
By the way, it seems the issue
https://github.com/sympy/sympy/issues/10963 is fixed in master (but
not in 1.0), so there you can do
In [3]: x = Symbol('x')
In [4]: expr = x**6000%400
In [7]: expr.evalf(950, subs={x:Float('1.4142', 950)})
Out[7]:
271.04818100863092181593910948838929251832458036234491201894546248073154256753666973207104639844775979650788048282365959816813533178603279338858556002378463
745117187500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000
But note even there you get the wrong answer unless you create 1.4142
as a Float with precision 950.
In [6]: expr.evalf(950, subs={x:1.4142})
Out[6]:
397.92898251746155210046958579278755870619830529784805636903899631078936617612319719713188467826854090314235414634273414074584762634145818083197809755802154
541015625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000
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.
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/CAHVvXxRWe%2BDykG15%3Dks%2Bs04mF%2BgS2LmtRJ_kmAWQdwXNHAg5Bw%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%3D6%2BQOUSyJh15pMgcTUYHbyWTVa26yb1XBfauv1SPZa_Jew%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.