Built-in Types ... INT: round or truncate ? please elaborate

I’m questioning about: Built-in Types - Numeric Types - int[…] - note(3)

irrc in PY2 it said:
Conversion from floats using int() truncates toward zero like the related function, math.trunc(). […]
now it says (note 3.):
Conversion from floating point to integer may round or truncate as in C […]
and nothing else…

1st off: is this really true?
a conversion from float to integer by: int(x) can result in (e.g.)math.round(x) ?

2nd and if so: when?
under what circumstances the conversion from FLOAT to INT by int(x):
-result in: math.trunc(x)
-or result in: math.round(x)

I consider myself an amateur; so this may be my fault, if so, please tell me; but please tell me where to find the answer. As long as it is not assembler, I’m confident to find answers in source-code too.

thanx for any answers in advance greets lichtwicht

I could think of some “precision-problems” that would make it more sensible to favor round instead trunc; still, I’d think it better to stick to ONE solution…(?)

Congratulations! You found a line of the docs that’s substantially unchanged since it was introduced almost 30 years ago: cpython/libtypes.tex at 557ed94ebbad49ec0f1ffa1b1b911a4ba1162c51 · python/cpython · GitHub

And no, it’s no longer true, and should be fixed. In current versions of CPython, int applied to a float will always truncate. In fact, the current implementation uses exactly the same code for float.__int__ as for float.__trunc__. See cpython/floatobject.c at 80abd62647b2a36947a11a6a8e395061be6f0c61 · python/cpython · GitHub.

Are you interested in opening a GitHub issue (or even better, a PR)?

As to why that note was there in the first place: I can only speculate, but my guess is that when the note was originally written (which may have been some time prior to the linked 1995 commit), it couldn’t reasonably be assumed that every C compiler followed the C89 standard, so the precise semantics of conversion from double to long couldn’t be relied upon.

Post standardisation, things are much clearer: C89 section (“Floating and integral”) starts with:

When a value of floating type is converted to integral type, the fractional part is discarded. […]

EDIT: Here’s the relevant code at the time for float to int conversion: cpython/floatobject.c at 5fdeeeae2a12b9956cc84d62eae82f72cabc8664 · python/cpython · GitHub

static object *
	object *v;
	double x = getfloatvalue(v);
	/* XXX should check for overflow */
	/* XXX should define how we round */
	return newintobject((long)x);
1 Like

many thanks for your detailed explanation!

(can I answer “not really” ?)
I’m not so versed with GitHub(in fact just registered for this question).
I’d be happy if the error in the doc just be corrected.
But of course I can (try to) do it…
(what’s a PR?)

Of course!

Ah, sorry. PR = “Pull Request”, which is the mechanism by which changes are proposed for CPython (and other GitHub-hosted projects). See Pull requests documentation - GitHub Docs for much more. (And if you’re interested in contributing to CPython at any point in the future, the Developer’s Guide is your friend.)

I’ve made a PR here: Fix outdated note about 'int' rounding or truncating by mdickinson · Pull Request #102736 · python/cpython · GitHub

1 Like