How can I simulate GNU C Library drem / remainder function in Google App Engine Python 2.7 runtime?
c, c++, gnu, google-app-engine, python
Solution
The key to solving this problem is to realise that the `drem`/`remainder` function specification requires the internal rounding calculation to round to half even.
Therefore we cannot use the built-in `round` function in Python 2.x as it rounds away from 0. However the `round` function in Python 3.x has changed to round to half even. So the following Python 3.x code will be equivalent to the GNU C Library `drem` function but will not work in Python 2.x:
def drem(x, y):
n = round(x / y)
return x - n * y
To achieve the same with Python 2.x we can use the decimal module and its remainder_near function:
import decimal
def drem(x, y):
xd = decimal.Decimal(x)
yd = decimal.Decimal(y)
return float(xd.remainder_near(yd))
Problem
The GNU C Library has the function `drem` (alias `remainder`). How can I simulate this function just using the modules supported by Google App Engine Python 2.7 runtime? From the GNU manual for `drem`: These functions are like `fmod` except that they round the internal quotient n to the nearest integer instead of towards zero to an integer. For example, drem (6.5, 2.3) returns -0.4, which is 6.5 minus 6.9. From the GNU manual for `fmod`: These functions compute the remainder from the division of numerator by denominator. Specifically, the return value is numerator - n * denominator, where n is the quotient of numerator divided by denominator, rounded towards zero to an integer. Thus, fmod (6.5, 2.3) returns 1.9, which is 6.5 minus 4.6. Reading the documentation the following Python code should work: ``` def drem(x, y): n = round(x / y) return x - n * y ``` However with Python, `drem(1.0, 2.0) == -1.0` and with C `drem(1.0, 2.0) == 1.0`. Note Python returns negative one and C returns positive one. This is almost certainly an internal difference in rounding floats. As far as I can tell both functions perform the same otherwise where parameters `2 * x != y`. How can I make my Python `drem` function work the same as its C equivalent?