[Python-Dev] Change in Python 3's "round" behavior

jab at math.brown.edu jab at math.brown.edu
Wed Sep 26 07:26:17 EDT 2018

I recently found out about Python 3's round-to-even change (via
https://github.com/cosmologicon/pywat!) and am having trouble finding
where that change was discussed.

I did find the revealingly-invalid bug report
https://bugs.python.org/issue32956 ("python 3 round bug"), so I asked
there, but wanted to invite anyone else on this list who might be
interested to help. If interested, please see the comments there
(copy/pasted below for convenience), and +nosy or comment on that


Joshua Bronson added the comment:

This was so surprising to me that I had to check some other languages
that I had handy. It turns out that not one of JavaScript, Ruby, Perl,
C++, Java, Go, or Rust agrees with Python. In fact they all agreed
with one another that 2.5 should round to 3. Examples below.

I understand from
that "to always round up... can theoretically skew the data" but it's
not clear why that's a good enough reason to differ from the "round"
function in all these other languages (as opposed to e.g. offering
this alternative behavior in some additional "round_unskewed"

I assume the rationale for having Python 3's "round" differ from that
of so many other languages was written down when this decision was
made, but I searched and couldn't find it. Could anyone link to it in
a comment here?

And would it be worth including rationale and a larger callout in the
https://docs.python.org/3/library/functions.html#round docs? The
documentation of this behavior is a bit buried among other things, and
the rationale for it is missing entirely.

$ node -e 'console.log(Math.round(2.5))'

$ ruby -e 'puts (2.5).round()'

$ perl -e 'use Math::Round; print round(2.5)'

$ cat test_round.cpp
#include <stdio.h>
#include <math.h>
int main(void) {
  printf("%f\n", round(2.5));
$ g++ test_round.cpp && ./a.out

$ cat TestRound.java
class TestRound {
  public static void main(String[] args) {
$ javac TestRound.java && java TestRound

$ cat test_round.go
package main
import "fmt"
import "math"
func main() {
$ go build test_round.go && ./test_round

$ cat test_round.rs
fn main() {
  println!("{}", (2.5_f64).round());
$ rustc test_round.rs && ./test_round

Serhiy Storchaka added the comment:

See the discussion on the Python-Dev mailing list:

For C look at the rint() function. It is a common knowledge that
rounding half-to-even is what users want in most cases, but it is a
tiny bit more expensive in C. In Python the additional cost of such
rounding is insignificant.

Joshua Bronson added the comment:

Thanks Serhiy, I read the Python-Dev thread you linked to, but that
doesn't resolve the issues:

- Its topic is Python 2.6 (where this behavior does not occur) rather
than Python 3 (where it does).

- A few messages into the thread Guido does address Python 3, but in
fact says "I think the consensus is against round-to-even in 3.0" (see

- There is no discussion of the fact that this behavior differs from
the function named "round" in all the other programming languages I
mentioned, and whether it would therefore be better exposed as an
additional function (e.g. "round_to_even" or "round_unbiased", and in
the math or statistics package rather than builtins). Surprisingly,
Excel is the only other programming environment I saw discussed in the
thread. (And round(2.5) == 3 there.)

So that all suggests there must be some other thread or issue where
this change for Python 3 have been discussed, but I looked again and
could not find it.

The C "rint" example you gave just seems to prove the point that this
behavior should have a distinct name from "round".

> It is a common knowledge that rounding half-to-even is what users want in most cases

I don't think that's common knowledge; seems like citation needed?
Based on all the other languages where this differs (not to mention
Python 2), it's not clear users would want Python 3 to be the only
different one. And this is definitely a surprise for the majority of
programmers, whose experience with "round" is how it works everywhere
else. (This is making it into pywat after all:

I can submit a PR for at least updating the docs about this (as per my
previous comment) if that would be welcomed.

More information about the Python-Dev mailing list