Question about the rounding functions

Hi,
So while I was solving a DSA question where in which you have to round the final answer to the nearest millionth, I stumbled across this weird scenario:

Take the decimal 9.1919575. round(9.1919575, 6) or even f"{9.1919575:.6f}" (which rounds to the 2nd-to-last decimal place) returns 9.191957. But this doesn’t make sense because bankers’ rounding and the one we are usually taught in elementary school both should output 9.191958.

What makes it even more nonsensical is that rounding 9.75 (i.e. taking out the extraneous middle digits) to the nearest tenth with either method (f-strings or round) returns 9.8 as it should instead of 9.7 as the previous example would suggest.

So I have 2 questions:

  1. Why is it returning the “correct” answer only when the middle four digits are removed?
  2. Is there an alternative method to rounding that would achieve the “correct” result with either input (besides making a new function manually)?

It does, because Python floats are binary floating-point numbers. You can see in round() docs:

The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float. See Floating-Point Arithmetic: Issues and Limitations for more information.

(Sometimes it’s worth to look on docs :wink: )

You can use the decimal module instead. In also supports rounding to nearest (with ties to even) as default rounding mode. That give you something expected as result:

>>> from decimal import Decimal
>>> round(Decimal('9.1919575'), 6)
Decimal('9.191958')
>>> f"{Decimal('9.1919575'):.6f}"
'9.191958'

Note what happens if you pass a float value instead:

>>> round(Decimal(9.1919575), 6)
Decimal('9.191957')
>>> f"{Decimal(9.1919575):.6f}"
'9.191957'

That’s because:

>>> Decimal(9.1919575)
Decimal('9.1919574999999991149479683372192084789276123046875')

So, for your questions:

Because such binary floating-point number just have a different value. And it’s rounding give you something expected for a decimal floating-point number.

Rounding of floats is correct, as it was explained above. No, for floats — only one rounding mode is supported (round to nearest). Use decimal module if you expect decimal floating-point arithmetic. The decimal module supports more rounding modes.

A lot of the time floating point math can make things look a bit weird because of internal numeric representation. See 15. Floating-Point Arithmetic: Issues and Limitations — Python 3.13.4 documentation for some more details.

For when this level of rounding matters more, consider using something like decimal — Decimal fixed-point and floating-point arithmetic — Python 3.13.4 documentation.