The fact that the numbers are stored in binary is significant: In [16]: nums = [eval('1.%d5' % n) for n in range(10)]
In [17]: nums Out[17]: [1.05, 1.15, 1.25, 1.35, 1.45, 1.55, 1.65, 1.75, 1.85, 1.95] In [18]: [round(n, 1) for n in nums] Out[18]: [1.1, 1.1, 1.2, 1.4, 1.4, 1.6, 1.6, 1.8, 1.9, 1.9] Proper decimal rounding might look like: In [20]: from decimal import Decimal In [21]: nums = [Decimal('1.%d5' % n) for n in range(10)] In [22]: nums Out[22]: [Decimal('1.05'), Decimal('1.15'), Decimal('1.25'), Decimal('1.35'), Decimal('1.45'), Decimal('1.55'), Decimal('1.65'), Decimal('1.75'), Decimal('1.85'), Decimal('1.95') In [23]: [round(n, 1) for n in nums] Out[23]: [Decimal('1.1'), Decimal('1.2'), Decimal('1.3'), Decimal('1.4'), Decimal('1.5'), Decimal('1.6'), Decimal('1.7'), Decimal('1.8'), Decimal('1.9'), Decimal('2.0')] Or with half-even rounding: In [24]: from decimal import getcontext In [25]: getcontext().rounding = 'ROUND_HALF_EVEN' In [26]: [round(n, 1) for n in nums] Out[26]: [Decimal('1.0'), Decimal('1.2'), Decimal('1.2'), Decimal('1.4'), Decimal('1.4'), Decimal('1.6'), Decimal('1.6'), Decimal('1.8'), Decimal('1.8'), Decimal('2.0')] The binary floats don't work out correct because some are above and some are below the number suggested by the original float literal. On Thu, 11 Apr 2019 at 02:03, Chris Smith <smi...@gmail.com> wrote: > > That floats are stored in binary is an implementation detail which need not > prevent base-10 rounding to still work. The 2nd argument to round is intended > to tell at which base-10 digit the rounding is to take place. By shifting > that digit to the ones position and then doing the rounding one can easily > detect whether what follows is above or below a half. > > >>> .345.as_integer_ratio() > (1553741871442821, 4503599627370496) > >>> (_*100).as_integer_ratio() > (69, 2) > > "round to even" means "if what follows the digit to which you are rounding is > 5 then round so your digit is even". As is shown in the integer ratios above, > what follows the 4 is exactly 1/2 so we can round to the even 4 (as in .34) > instead of the odd 5 (as in .35) just like round(0.75,1) rounds to 0.8 while > round(0.25) rounds to 0.2. > > On Wednesday, April 10, 2019 at 7:29:18 PM UTC-5, Aaron Meurer wrote: >> >> Doesn't Python do rounding based on the binary representation of the float? >> >> I'm a little confused what "round to even" means in that case. >> >> Aaron Meurer >> >> On Wed, Apr 10, 2019 at 6:16 PM Chris Smith <smi...@gmail.com> wrote: >> > >> > Python 3 implements "round to even on tie" logic so `round(12.5)` -> 12, >> > not 13. I have updated, in #16608, the round function but there is a >> > difference in how ties are detected. I shift the desired position to the >> > ones position and then check for a tie so 12.345 is shifted to 1234.5 and >> > rounded to 1234 then is divided by 100 to give 12.34. Python doesn't do >> > this. I suspect it adds 0.05 and then detects that12.395 > 12395/1000 and >> > rounds up to 12.35 >> > >> > >> > >>> Rational(*.345.as_integer_ratio())-Rational(345,1000) # .345 < >> > >>> 345/1000 >> > -3/112589990684262400 >> > >>> Rational(*.395.as_integer_ratio())-Rational(395,1000) # .395 > >> > >>> 395/1000 >> > 1/56294995342131200 >> > >> > >> > >>> round(12.345,2) # 12.345 rounds up b/c a tie is not detected >> > 12.35 >> > >> > >> > >> > Does anyone have objections to the proposed rounding? >> > >> > /c >> > >> > -- >> > 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 sy...@googlegroups.com. >> > To post to this group, send email to sy...@googlegroups.com. >> > 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/a84085c6-aa90-437c-b063-a87f909beac4%40googlegroups.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 sympy+unsubscr...@googlegroups.com. > To post to this group, send email to sympy@googlegroups.com. > 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/7873bfe6-6f91-4d39-af6f-9f4039714fa8%40googlegroups.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 sympy+unsubscr...@googlegroups.com. To post to this group, send email to sympy@googlegroups.com. 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/CAHVvXxTJQS4nC5TOL5nvAE5P2YQ97dLr%2BD3zApgrL%2BpVPoXz%3DQ%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.