From d84a5aed8e37abd3210bd73ca7f31321ef6efd44 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sun, 26 Jan 2025 02:01:45 -0500 Subject: [PATCH 1/2] gh-75204: Clarify int division programming faq Explain the alternative choices for int division (//) and modulo (i % j) sign determination. Mention that some languages choose truncation and 'i' determination. Justify Python's choice of flooring and 'j' determination. --- Doc/faq/programming.rst | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index 776bab1ed5b779..ce0cfbf1171d0b 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -825,23 +825,23 @@ or uppercase. For example, in the Python interpreter:: 178 -Why does -22 // 10 return -3? ------------------------------ - -It's primarily driven by the desire that ``i % j`` have the same sign as ``j``. -If you want that, and also want:: - - i == (i // j) * j + (i % j) - -then integer division has to return the floor. C also requires that identity to -hold, and then compilers that truncate ``i // j`` need to make ``i % j`` have -the same sign as ``i``. - -There are few real use cases for ``i % j`` when ``j`` is negative. When ``j`` -is positive, there are many, and in virtually all of them it's more useful for -``i % j`` to be ``>= 0``. If the clock says 10 now, what did it say 200 hours -ago? ``-190 % 12 == 2`` is useful; ``-190 % 12 == -10`` is a bug waiting to -bite. +Why does -22 // 10 return -3 instead of -2? +------------------------------------------- + +A non-integral float, such as ``x = -22 / 10``, can be converted to an int +with either :meth:`math.trunc` or :meth:`math.floor`, giving -2 or -3. +Maintaining the desired invariant ``i == (i // j) * j + (i % j)`` requires +that the choice for integer division (`//`) match the choice for which of +``i`` or ``j`` determines the sign of ``i % j``. For -22 and 10, ``-2*10 + (-2) == +-3*10 + 8 == -22``. Some languages choose truncation for int division +and hence modulo sign determination by ``i``. + +Python chose floor division primarily to make ``i % j`` have the same sign +as ``j``. There are few real use cases for ``i % j`` when ``j`` is negative, +but many for positive ``j``, and in nearly all of them it is +more useful for ``i % j`` to be ``>= 0``. If a clock says 10 now, what did it +say 200 hours ago? ``-190 % 12 == 2`` is useful. Making ``-190 % 12`` be ``-10`` +would have often been a bug waiting to happen. How do I get int literal attribute instead of SyntaxError? From 4fec34d0a7d2be83488d6f8022d4dda7870f7300 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sun, 26 Jan 2025 02:20:02 -0500 Subject: [PATCH 2/2] Double backslash --- Doc/faq/programming.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index ce0cfbf1171d0b..47833c1026cf2b 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -831,7 +831,7 @@ Why does -22 // 10 return -3 instead of -2? A non-integral float, such as ``x = -22 / 10``, can be converted to an int with either :meth:`math.trunc` or :meth:`math.floor`, giving -2 or -3. Maintaining the desired invariant ``i == (i // j) * j + (i % j)`` requires -that the choice for integer division (`//`) match the choice for which of +that the choice for integer division (``//``) match the choice for which of ``i`` or ``j`` determines the sign of ``i % j``. For -22 and 10, ``-2*10 + (-2) == -3*10 + 8 == -22``. Some languages choose truncation for int division and hence modulo sign determination by ``i``.