evalf and Integer

19 views
Skip to first unread message

Paul Royik

unread,
Aug 1, 2021, 6:02:47 AM8/1/21
to sympy
For a given number, I want to approximate it to 5 decimal points.
If a number of digits in the integer part is greater than 7, then round to 7 significant figures.

What I noticed is that evalf doesn't approximate to decimal points, it evaluates to significant figures.

What should I apply to get the desired result? It appears that round is a buggy.

Also, I noticed, that Integer(sqrt(101010101).evalf(3)) gives 10050, while (sqrt(101010101).evalf(3) gives 10100.

Is it expected behaviour?

Thank you.

Oscar Benjamin

unread,
Aug 1, 2021, 7:40:28 AM8/1/21
to sy...@googlegroups.com
On Sun, 1 Aug 2021 at 11:02, Paul Royik <distan...@gmail.com> wrote:
>
> For a given number, I want to approximate it to 5 decimal points.
> If a number of digits in the integer part is greater than 7, then round to 7 significant figures.

What does "round" mean here? Do you want to round to nearest, or round
towards zero, round towards minus infinity? How should ties be
handled?

Maybe this does what you want:

In [12]: f = sqrt(101010101010101)

In [13]: f5 = round(f, 5)

In [14]: f5
Out[14]: 10050378.15259

In [15]: floor(f5) > 10**7
Out[15]: True

In [16]: numdigits = len(str(floor(f5)))

In [17]: numdigits
Out[17]: 8

In [18]: f7 = round(f, 7 - numdigits)

In [19]: f7
Out[19]: 10050380.0000000

> What I noticed is that evalf doesn't approximate to decimal points, it evaluates to significant figures.

More precisely it rounds to a given number of binary (not decimal) digits.

> What should I apply to get the desired result? It appears that round is a buggy.

It's not clear exactly what you want but maybe the code I showed above
works. What do you mean that round is buggy?

> Also, I noticed, that Integer(sqrt(101010101).evalf(3)) gives 10050, while (sqrt(101010101).evalf(3) gives 10100.
>
> Is it expected behaviour?

When you ask for sqrt(101010101).evalf(3) the result is supposed to be
precise to 3 decimal digits but in the face of rounding it is always
possible that the last digit may not be the correct digit for the true
answer since in some cases an arbitrarily large precision is needed to
get a correct answer for the nth digit. The exact value returned is:

In [27]: f = sqrt(101010101).evalf(3)

In [28]: f._mpf_
Out[28]: (0, mpz(5025), 1, 13)

In [29]: f._prec
Out[29]: 13

In [30]: 5025*2**1
Out[30]: 10050

The exact value of the Float is 10050 but it has a (binary) precision
of 13 digits which is what is used for a decimal precision of ~3
digits. When printing the result is rounded to 3 decimal digits and
the 50 rounds up to 100. When you call Integer(f) that returns the
integer 10050 which displays as that exact value.

--
Oscar

Aaron Meurer

unread,
Aug 2, 2021, 6:28:10 PM8/2/21
to sympy
sqrt(101010101).round(-2) gives 10100 as expected. The docstring
states that it does decimal rounding, although I haven't played with
it enough to confirm if this is actually the case.

I think we should add some flags to the round() method. It would be
useful to control whether the rounding is base-10 or base-2, the
rounding type (toward 0/infinity/negative infinity, toward even,
etc.), and whether the input represents the number of digits after the
decimal place or the total number of digits.

Aaron Meurer
> --
> 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 sympy+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/CAHVvXxR9XUNs2Jj-0vumwPf6LC0-SVT2qZfjCXZH6gyFiZ_CRA%40mail.gmail.com.
Reply all
Reply to author
Forward
0 new messages