How to implement division with round-towards-infinity in Python - python

I want 3/2 to equal 2 not 1.5
I know there's a mathematical term for that operation(not called rounding up), but I can't recall it right now.
Anyway, how do i do that without having to do two functions?
ex of what I do NOT want:
answer = 3/2 then math.ceil(answer)=2 (why does math.ceil(3/2)=1?)
ex of what I DO want:
"function"(3/2) = 2

To give a short answer...
Python only offers native operators for two types of division: "true" division, and "round down" division. So what you want isn't available as a single function. However, it is possible to easily implement a number of different types of division-with-rounding using some short expressions.
Per the title's request: given strictly integer inputs, "round up" division can be implemented using (a+(-a%b))//b, and "round away from zero" division can be implemented using the more complex a//b if a*b<0 else (a+(-a%b))//b. One of those is probably what you want. As to why...
To give a longer answer...
First, let me answer the subquestion about why 3/2==1 and math.ceil(3/2)==1.0, by way of explaining how the Python division operator works. There are two main issues at play...
float vs int division: Under Python 2, division behaves differently depending on the type of the inputs. If both a and b are integers, a/b performs "round down" or "floor integer" division (eg 3/2==1, but -3/2==-2). This is equivalent to int(math.floor(float(a)/b)) .
But if at least one of a and b are floats, Python performs "true" division, and gives you a float result (eg 3.0/2==1.5, and -3.0/2==-1.5). This is why you'll sometimes see the construction float(a)/b: it's being used to force true division even both inputs are integers (eg float(3)/2==1.5). This is why your example math.ceil(3/2) returns 1.0, whereas math.ceil(float(3)/2) returns 2.0. The result has already been rounded down before it even reaches math.ceil().
"true division" by default: In 2001, it was decided (PEP 238) that Python's division operator should be changed so that it always performs "true" division, regardless of whether the inputs are floats or integers (eg, this would make 3/2==1.5). In order to not break existing scripts, the change in default behavior was deferred until Python 3.0; in order to get this behavior under Python 2.x, you have to enable it per-file by adding from __future__ import division to the top of the file. Otherwise the old type-dependant behavior is used.
But "round down" division is still frequently needed, so the PEP didn't do way with it entirely. Instead, it introduced a new division operator: a//b, which always performs round down division, even if the inputs include floats. This can be used without doing anything special under both Python 2.2+ and 3.x.
That out of that way, division-with-rounding:
In order to simplify things, the following expressions all use the a//b operator when working on integers, since it will behave the same under all python versions. As well, I'm making an assumption that 0<=a%b<b if b is positive, and b<=a%b<=0 if b is negative. This is how Python behaves, but other languages may have slightly different modulus operators.
The four basic types of integer division with rounding:
"round down" aka "floor integer" aka "round to minus infinity" divsion: python offers this natively via a//b.
"round up" aka "ceiling integer" aka "round to positive infinity" division: this can be achieved via int(math.ceil(float(a)/b)) or (a+(-a%b))//b. The latter equation works because -a%b is 0 if a is a multiple of b, and is otherwise the amount we need to add to a to get to the next highest multiple.
"round towards zero" aka "truncated" division - this can be achieved via int(float(a)/b). Doing this without using floating point is trickier... since Python only offers round-down integer division, and the % operator has a similar round-down bias, we don't have any non-floating-point operators which round symmetrically about 0. So the only way I can think of is to construct a piecewise expression out of round-down and round-up: a//b if a*b>0 else (a+(-a%b))//b.
"round away from zero" aka "round to (either) infinity" division - unfortunately, this is even trickier than round-towards-zero. We can't leverage the truncating behavior of the int operator anymore, so I can't think of a simple expression even when including floating-point ops. So I have to go with the inverse of the round-to-zero expression, and use a//b if a*b<0 else (a+(-a%b))//b.
Note that if you're only using positive integers, (a+b-1)//b provides round up / away from zero even more efficiently than any of the above solutions, but falls apart for negatives.
Hope that helps... and happy to make edits if anyone can suggest better equations for round to/away from zero. I find the ones I have particularly unsatisfactory.

Integral division in Python 3:
3 // 2 == 1
Non-integral division in Python 3:
3 / 2 == 1.5
What you're talking about is not a division by all means.

The intent of the OP's question is "How to implement division with round-towards-infinity in Python" (suggest you change the title).
This is a perfectly legitimate rounding mode as per the IEEE-754 standard (read this overview), and the term for it is "round towards infinity" (or "round away from zero"). Most of the 9 downvotes were beating up on the OP unfairly. Yes, there is no single-function way to do this in native Python, but we can use round(float(a)/b) or else subclass numbers.Number and override __div__().
The OP would need to clarify whether they want -3/2 to round to -2 or -1 (or don't-care for negative operands). Since they already said they don't want round-upwards, we can infer -3/2 should round to -2.
Enough theory. For implementations:
If you just want the fast-and-dirty one-line solution for round-towards-infinity , use round(float(a)/b)
math.ceil(float(a)/b) gives you round-upwards, which you said you don't want
But if this is your default division operation, or you are doing a lot of this, then do like the pseudocode below: inherit from one of the subclasses of numbers.Number Real, Rational or Integral (new in 2.6), redefine __div__() or else define a non-default alternative __divra__() operation. You could define a class member or classmethod rounding_mode and look it up during divisions. Be careful of __rdiv__() and mixing with ordinary floats though.
.
import numbers
class NumberWithRounding(numbers.Integral):
# Here you could implement a classmethod setRoundingMode() or member rounding_mode
def __div__(self,other):
# here you could consider value of rounding_mode, or else hardwire it like:
return round(float(self)/other)
# You also have to raise ImplementationError/ pass/ or implement the other 31
# methods for Float: __abs__(),...,__xor__() Just shortcut that for now...

When you divide two integers, the result is an integer.
3 / 2 equals 1, not 1.5.
See the documentation, note 1:
For (plain or long) integer division, the result is an integer. The result is always rounded towards minus infinity: 1/2 is 0, (-1)/2 is -1, 1/(-2) is -1, and (-1)/(-2) is 0. Note that the result is a long integer if either operand is a long integer, regardless of the numeric value.
Once you get 1 from the division, there is no way to turn that into 2.
To get 1.5, you need floating-point division: 3.0 / 2.
You can then call math.ceil to get 2.
You are mistaken; there is no mathematical function that divides, then rounds up.
The best you can do is write your own function that takes two floats and calls math.ceil.

What you probably want is something like:
math.ceil(3.0/2.0)
# or
math.ceil(float(3)/float(2))
You could also do an import from future:
from __future__ import division
math.ceil(3/2) # == 2
But, if you do this, to get the current behavior of integer division you need to use the double slash:
3 // 2 == 1 # True

Integer division with ceiling rounding (to +Inf), floor rounding (to -Inf), and truncation (to 0) is available in gmpy2.
>>> gmpy2.c_div(3,2)
mpz(2)
>>> help(gmpy2.c_div)
Help on built-in function c_div in module gmpy2:
c_div(...)
c_div(x,y): returns the quotient of x divided by y. The quotient
is rounded towards +Inf (ceiling rounding). x and y must be integers.
>>> help(gmpy2.f_div)
Help on built-in function f_div in module gmpy2:
f_div(...)
f_div(x,y): returns the quotient of x divided by y. The quotient
is rounded towards -Inf (floor rounding). x and y must be integers.
>>> help(gmpy2.t_div)
Help on built-in function t_div in module gmpy2:
t_div(...)
t_div(x,y): returns the quotient of x divided by y. The quotient
is rounded towards 0. x and y must be integers.
>>>
gmpy2 is available at http://code.google.com/p/gmpy/
(Disclaimer: I'm the current maintainer of gmpy and gmpy2.)

I think that what you're looking for is this:
assuming you have x (3) and y (2),
result = (x + y - 1) // y;
this is the equivalent of a ceiling without the use of floating points.
Of course, y cannot be 0.

Firstly, you want to be using floating-point division in the arguments. Use:
from __future__ import division
If you always want to round up, so f(3/2)==2 and f(1.4)==2, then you want f to be math.trunc(math.ceil(x)).
If you want to get the closest integer, but have ties round up, then you want math.trunc(x + 0.5). That way f(3/2)==2 and f(1.4)==1.

Related

Why Python builtin numeric type and decimal module differs on a same operation? [duplicate]

With simple ints:
>>> -45 % 360
315
Whereas, using a decimal.Decimal:
>>> from decimal import Decimal
>>> Decimal('-45') % 360
Decimal('-45')
I would expect to get Decimal('315').
Is there any reason for this? Is there a way to get a consistent behaviour (without patching decimal.Decimal)? (I did not change the context, and cannot find how it could be changed to solve this situation).
After a long search (because searching on "%", "mod", "modulo" etc. gives a thousand of results), I finally found that, surprisingly, this is intended:
There are some small differences between arithmetic on Decimal objects
and arithmetic on integers and floats. When the remainder operator %
is applied to Decimal objects, the sign of the result is the sign of
the dividend rather than the sign of the divisor:
>>> (-7) % 4
1
>>> Decimal(-7) % Decimal(4)
Decimal('-3')
I don't know the reason for this, but it looks like it's not possible to change this behaviour (without patching).
Python behaves according to IBM's General Decimal Arithmetic Specification.
The remainder is defined as:
remainder takes two operands; it returns the remainder from integer division. […]
the result is the residue of the dividend after the operation of calculating integer division as described for divide-integer, rounded to precision digits if necessary. The sign of the result, if non-zero, is the same as that of the original dividend.
So because Decimal('-45') // D('360') is Decimal('-0'), the remainder can only be Decimal('-45').
Though why is the quotient 0 and not -1? The specification says:
divide-integer takes two operands; it divides two numbers and returns the integer part of the result. […]
the result returned is defined to be that which would result from repeatedly subtracting the divisor from the dividend while the dividend is larger than or equal to the divisor. During this subtraction, the absolute values of both the dividend and the divisor are used: the sign of the final result is the same as that which would result if normal division were used. […]
Notes: […]
The divide-integer and remainder operations are defined so that they may be calculated as a by-product of the standard division operation (described above). The division process is ended as soon as the integer result is available; the residue of the dividend is the remainder.
How many times can you subtract 360 from 45? 0 times. Is an integer result available? It is. Then the quotient is 0 with a minus sign because the divide operation says that
The sign of the result is the exclusive or of the signs of the operands.
As for why the Decimal Specification goes on this route, instead of doing it like in math where the remainder is always positive, I'm speculating that it could be for the simplicity of the subtraction algorithm. No need to check the sign of the operands in order to compute the absolute value of the quotient. Modern implementations probably use more complicated algorithms anyway, but simplicity could be have an important factor back in the days when the standard was taking form and hardware was simpler (way fewer transistors). Fun fact: Intel switched from radix-2 integer division to radix-16 only in 2007 with the release of Penryn.

Comparing two floats in python [duplicate]

It's well known that comparing floats for equality is a little fiddly due to rounding and precision issues.
For example: Comparing Floating Point Numbers, 2012 Edition
What is the recommended way to deal with this in Python?
Is a standard library function for this somewhere?
Python 3.5 adds the math.isclose and cmath.isclose functions as described in PEP 485.
If you're using an earlier version of Python, the equivalent function is given in the documentation.
def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
rel_tol is a relative tolerance, it is multiplied by the greater of the magnitudes of the two arguments; as the values get larger, so does the allowed difference between them while still considering them equal.
abs_tol is an absolute tolerance that is applied as-is in all cases. If the difference is less than either of those tolerances, the values are considered equal.
Something as simple as the following may be good enough:
return abs(f1 - f2) <= allowed_error
I would agree that Gareth's answer is probably most appropriate as a lightweight function/solution.
But I thought it would be helpful to note that if you are using NumPy or are considering it, there is a packaged function for this.
numpy.isclose(a, b, rtol=1e-05, atol=1e-08, equal_nan=False)
A little disclaimer though: installing NumPy can be a non-trivial experience depending on your platform.
Use Python's decimal module, which provides the Decimal class.
From the comments:
It is worth noting that if you're
doing math-heavy work and you don't
absolutely need the precision from
decimal, this can really bog things
down. Floats are way, way faster to
deal with, but imprecise. Decimals are
extremely precise but slow.
The common wisdom that floating-point numbers cannot be compared for equality is inaccurate. Floating-point numbers are no different from integers: If you evaluate "a == b", you will get true if they are identical numbers and false otherwise (with the understanding that two NaNs are of course not identical numbers).
The actual problem is this: If I have done some calculations and am not sure the two numbers I have to compare are exactly correct, then what? This problem is the same for floating-point as it is for integers. If you evaluate the integer expression "7/3*3", it will not compare equal to "7*3/3".
So suppose we asked "How do I compare integers for equality?" in such a situation. There is no single answer; what you should do depends on the specific situation, notably what sort of errors you have and what you want to achieve.
Here are some possible choices.
If you want to get a "true" result if the mathematically exact numbers would be equal, then you might try to use the properties of the calculations you perform to prove that you get the same errors in the two numbers. If that is feasible, and you compare two numbers that result from expressions that would give equal numbers if computed exactly, then you will get "true" from the comparison. Another approach is that you might analyze the properties of the calculations and prove that the error never exceeds a certain amount, perhaps an absolute amount or an amount relative to one of the inputs or one of the outputs. In that case, you can ask whether the two calculated numbers differ by at most that amount, and return "true" if they are within the interval. If you cannot prove an error bound, you might guess and hope for the best. One way of guessing is to evaluate many random samples and see what sort of distribution you get in the results.
Of course, since we only set the requirement that you get "true" if the mathematically exact results are equal, we left open the possibility that you get "true" even if they are unequal. (In fact, we can satisfy the requirement by always returning "true". This makes the calculation simple but is generally undesirable, so I will discuss improving the situation below.)
If you want to get a "false" result if the mathematically exact numbers would be unequal, you need to prove that your evaluation of the numbers yields different numbers if the mathematically exact numbers would be unequal. This may be impossible for practical purposes in many common situations. So let us consider an alternative.
A useful requirement might be that we get a "false" result if the mathematically exact numbers differ by more than a certain amount. For example, perhaps we are going to calculate where a ball thrown in a computer game traveled, and we want to know whether it struck a bat. In this case, we certainly want to get "true" if the ball strikes the bat, and we want to get "false" if the ball is far from the bat, and we can accept an incorrect "true" answer if the ball in a mathematically exact simulation missed the bat but is within a millimeter of hitting the bat. In that case, we need to prove (or guess/estimate) that our calculation of the ball's position and the bat's position have a combined error of at most one millimeter (for all positions of interest). This would allow us to always return "false" if the ball and bat are more than a millimeter apart, to return "true" if they touch, and to return "true" if they are close enough to be acceptable.
So, how you decide what to return when comparing floating-point numbers depends very much on your specific situation.
As to how you go about proving error bounds for calculations, that can be a complicated subject. Any floating-point implementation using the IEEE 754 standard in round-to-nearest mode returns the floating-point number nearest to the exact result for any basic operation (notably multiplication, division, addition, subtraction, square root). (In case of tie, round so the low bit is even.) (Be particularly careful about square root and division; your language implementation might use methods that do not conform to IEEE 754 for those.) Because of this requirement, we know the error in a single result is at most 1/2 of the value of the least significant bit. (If it were more, the rounding would have gone to a different number that is within 1/2 the value.)
Going on from there gets substantially more complicated; the next step is performing an operation where one of the inputs already has some error. For simple expressions, these errors can be followed through the calculations to reach a bound on the final error. In practice, this is only done in a few situations, such as working on a high-quality mathematics library. And, of course, you need precise control over exactly which operations are performed. High-level languages often give the compiler a lot of slack, so you might not know in which order operations are performed.
There is much more that could be (and is) written about this topic, but I have to stop there. In summary, the answer is: There is no library routine for this comparison because there is no single solution that fits most needs that is worth putting into a library routine. (If comparing with a relative or absolute error interval suffices for you, you can do it simply without a library routine.)
math.isclose() has been added to Python 3.5 for that (source code). Here is a port of it to Python 2. It's difference from one-liner of Mark Ransom is that it can handle "inf" and "-inf" properly.
def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
'''
Python 2 implementation of Python 3.5 math.isclose()
https://github.com/python/cpython/blob/v3.5.10/Modules/mathmodule.c#L1993
'''
# sanity check on the inputs
if rel_tol < 0 or abs_tol < 0:
raise ValueError("tolerances must be non-negative")
# short circuit exact equality -- needed to catch two infinities of
# the same sign. And perhaps speeds things up a bit sometimes.
if a == b:
return True
# This catches the case of two infinities of opposite sign, or
# one infinity and one finite number. Two infinities of opposite
# sign would otherwise have an infinite relative tolerance.
# Two infinities of the same sign are caught by the equality check
# above.
if math.isinf(a) or math.isinf(b):
return False
# now do the regular computation
# this is essentially the "weak" test from the Boost library
diff = math.fabs(b - a)
result = (((diff <= math.fabs(rel_tol * b)) or
(diff <= math.fabs(rel_tol * a))) or
(diff <= abs_tol))
return result
I'm not aware of anything in the Python standard library (or elsewhere) that implements Dawson's AlmostEqual2sComplement function. If that's the sort of behaviour you want, you'll have to implement it yourself. (In which case, rather than using Dawson's clever bitwise hacks you'd probably do better to use more conventional tests of the form if abs(a-b) <= eps1*(abs(a)+abs(b)) + eps2 or similar. To get Dawson-like behaviour you might say something like if abs(a-b) <= eps*max(EPS,abs(a),abs(b)) for some small fixed EPS; this isn't exactly the same as Dawson, but it's similar in spirit.
If you want to use it in testing/TDD context, I'd say this is a standard way:
from nose.tools import assert_almost_equals
assert_almost_equals(x, y, places=7) # The default is 7
In terms of absolute error, you can just check
if abs(a - b) <= error:
print("Almost equal")
Some information of why float act weird in Python:
Python 3 Tutorial 03 - if-else, logical operators and top beginner mistakes
You can also use math.isclose for relative errors.
This is useful for the case where you want to make sure two numbers are the same 'up to precision', and there isn't any need to specify the tolerance:
Find minimum precision of the two numbers
Round both of them to minimum precision and compare
def isclose(a, b):
astr = str(a)
aprec = len(astr.split('.')[1]) if '.' in astr else 0
bstr = str(b)
bprec = len(bstr.split('.')[1]) if '.' in bstr else 0
prec = min(aprec, bprec)
return round(a, prec) == round(b, prec)
As written, it only works for numbers without the 'e' in their string representation (meaning 0.9999999999995e-4 < number <= 0.9999999999995e11)
Example:
>>> isclose(10.0, 10.049)
True
>>> isclose(10.0, 10.05)
False
For some of the cases where you can affect the source number representation, you can represent them as fractions instead of floats, using integer numerator and denominator. That way you can have exact comparisons.
See Fraction from fractions module for details.
I liked Sesquipedal's suggestion, but with modification (a special use case when both values are 0 returns False). In my case, I was on Python 2.7 and just used a simple function:
if f1 ==0 and f2 == 0:
return True
else:
return abs(f1-f2) < tol*max(abs(f1),abs(f2))
If you want to do it in a testing or TDD context using the pytest package, here's how:
import pytest
PRECISION = 1e-3
def assert_almost_equal():
obtained_value = 99.99
expected_value = 100.00
assert obtained_value == pytest.approx(expected_value, PRECISION)
I found the following comparison helpful:
str(f1) == str(f2)
To compare up to a given decimal without atol/rtol:
def almost_equal(a, b, decimal=6):
return '{0:.{1}f}'.format(a, decimal) == '{0:.{1}f}'.format(b, decimal)
print(almost_equal(0.0, 0.0001, decimal=5)) # False
print(almost_equal(0.0, 0.0001, decimal=4)) # True
This maybe is a bit ugly hack, but it works pretty well when you don't need more than the default float precision (about 11 decimals).
The round_to function uses the format method from the built-in str class to round up the float to a string that represents the float with the number of decimals needed, and then applies the eval built-in function to the rounded float string to get back to the float numeric type.
The is_close function just applies a simple conditional to the rounded up float.
def round_to(float_num, prec):
return eval("'{:." + str(int(prec)) + "f}'.format(" + str(float_num) + ")")
def is_close(float_a, float_b, prec):
if round_to(float_a, prec) == round_to(float_b, prec):
return True
return False
>>>a = 10.0
10.0
>>>b = 10.0001
10.0001
>>>print is_close(a, b, prec=3)
True
>>>print is_close(a, b, prec=4)
False
Update:
As suggested by #stepehjfox, a cleaner way to build a rount_to function avoiding "eval" is using nested formatting:
def round_to(float_num, prec):
return '{:.{precision}f}'.format(float_num, precision=prec)
Following the same idea, the code can be even simpler using the great new f-strings (Python 3.6+):
def round_to(float_num, prec):
return f'{float_num:.{prec}f}'
So, we could even wrap it up all in one simple and clean 'is_close' function:
def is_close(a, b, prec):
return f'{a:.{prec}f}' == f'{b:.{prec}f}'
If you want to compare floats, the options above are great, but in my case, I ended up using Enum's, since I only had few valid floats my use case was accepting.
from enum import Enum
class HolidayMultipliers(Enum):
EMPLOYED_LESS_THAN_YEAR = 2.0
EMPLOYED_MORE_THAN_YEAR = 2.5
Then running:
testable_value = 2.0
HolidayMultipliers(testable_value)
If the float is valid, it's fine, but otherwise it will just throw an ValueError.
Use == is a simple good way, if you don't care about tolerance precisely.
# Python 3.8.5
>>> 1.0000000000001 == 1
False
>>> 1.00000000000001 == 1
True
But watch out for 0:
>>> 0 == 0.00000000000000000000000000000000000000000001
False
The 0 is always the zero.
Use math.isclose if you want to control the tolerance.
The default a == b is equivalent to math.isclose(a, b, rel_tol=1e-16, abs_tol=0).
If you still want to use == with a self-defined tolerance:
>>> class MyFloat(float):
def __eq__(self, another):
return math.isclose(self, another, rel_tol=0, abs_tol=0.001)
>>> a == MyFloat(0)
>>> a
0.0
>>> a == 0.001
True
So far, I didn't find anywhere to config it globally for float. Besides, mock is also not working for float.__eq__.

Why is -1/2 evaluated to 0 in C++, but -1 in Python?

C++: cout << -1/2 evaluates to 0
Python: -1/2 evaluates to -1.
Why is this the case?
Integer division in C++ rounds toward 0, and in Python, it rounds toward -infinity.
People dealing with these things in the abstract tend to feel that rounding toward negative infinity makes more sense (that means it's compatible with the modulo function as defined in mathematics, rather than % having a somewhat funny meaning). The tradition in programming languages is to round toward 0--this wasn't originally defined in C++ (following C's example at the time), but eventually C++ (and C) defined it this way, copying Fortran.
From the Python docs (emphasis mine):
The / (division) and // (floor division) operators yield the quotient of their arguments. The numeric arguments are first converted to a common type. Plain or long integer division yields an integer of the same type; the result is that of mathematical division with the ‘floor’ function applied to the result.
The floor function rounds to the number closest to negative infinity, hence -1.
For C++, from this reference: 5.2 — Arithmetic operators
It is easiest to think of the division operator as having two
different “modes”. If both of the operands are integers, the division
operator performs integer division. Integer division drops any
fractions and returns an integer value.
Thus, -1/2 would yield -0.5 with the fraction dropped, yielding 0.
As SethMMorton indicated, Python's rule is floor, which yields -1. It's described in 5. Expressions.
Put in the terms that Mike Graham mentioned, floor is a round toward minus infinity. Dropping the fraction is a round toward zero.
I am not sure about Python, but in C++ integer/integer = integer, and therefore in case of -1/2 is -0.5 which is rounded automatically to integer and therefore you get the 0 answer.
In case of Python, maybe the system used the floor function to convert the result into an integer.

Python gmpy2 f_divmod function confusion

I'm pretty new to python and i just started playing with gmpy2, but i'm a little confused about one of the functions and gmpy's documentation isn't helpful in this regard:
I'd like to do division with a modulus (as well as a floor) so i found the f_divmod() function:
f_divmod(...) f_divmod(x, y) returns the quotient and remainder of x
divided by y. The quotient is rounded towards -Inf (floor rounding)
and the remainder will have the same sign as y. x and y must be
integers.
However if this does what i think it should do (and that is probably my mistake), it should do: x / y % m, and i see no way to provide an m. Is this the wrong function for that, or do i need to somehow define a modulus elsewhere?
I see my alternative being:
c = gmpy2.f_div(a, b) % m
Thanks in advance!
Note: I maintain gmpy2.
gmpy2.f_divmod() (along with gmpy2.c_divmod(), gmpy2.t_divmod(), and gmpy2.divmod()) are patterned after the builtin divmod(). All the functions return the quotient and remainder but each functions uses a slightly different rule to compute the quotient and remainder. The names are meant to imply that the functions return the tuple (a // b, a % b). They don't do division followed by mod.
If you want to calculate the quotient using floor division, and then reduce that result modulo another number, then your alternative is correct.
Slightly off-topic hint: You should get into the habit of using // for integer division. In Python 3, / becomes floating point division. // is integer division in both Python 2 and 3.

Negative integer division surprising result

In my application I encountered the following and was surprised by the results:
8/-7=-2 (both integers).
What does this mean?
For the actual values, i.e. 8.0/(-7.0), the result is roughly -1.143.
Your result using integer division is being rounded down toward the more negative value of -2. (This is also known as "Floor division")
This is why you will get the somewhat perplexing answers of:
>>> 8/(-7)
-2
>>> 8/7
1
Note: This is "fixed" in Python 3, where the result of 8/(-7) would be -1.143. So if you have no reason to be using Python 2, you should upgrade. ;)
In Python 3, if you still want integer division, you can use the // operator. This will give you the same answer as 8/(-7) would in Python 2.
Here's a Python Enhancement Proposal on the subject: PEP 238 -- Changing the Division Operator
Python always does the "floor division" for both negative numbers division and positive numbers division.
That is
1/10 = 0
1/-10 = -1
But sometime we need 1/-10 to be 0
I figure out it can be done by using the float division first then cast result to int, e.g.
int(float(1)/-10) = 0
That works fine for me, no need to import the future division or upgrade to Python 3
Hope it can help you~
To have Python automatically convert integer division to float, you can use:
from __future__ import division
Now:
8/-7=-1.1428571428571428
This feature is not in the standard Python 2 not to break existing code that relied on integer division.
However, this is the default behavior for Python 3.
When both values are integers when dividing Python uses Floor division.
In Python, / operator is for integer division. You can look at it as float division followed by a floor operation.
For example,
8/7 == floor(8.0/7.0) == 1
8/-7 == floor(8.0/-7.0) == -2

Categories