I was surprised by the observation that Python rounds towards even numbers, so round(0.5) = 0, but round(1.5) = 2.<p>This is indeed clearly documented [1], I guess I never looked closely enough. I found some discussion on the dev-python list [2] which shows at least I'm not the only one surprised by this!<p>[1] <a href="https://docs.python.org/3/library/functions.html#round" rel="nofollow">https://docs.python.org/3/library/functions.html#round</a><p>[2] <a href="https://groups.google.com/g/dev-python/c/VNf8TABiB9k" rel="nofollow">https://groups.google.com/g/dev-python/c/VNf8TABiB9k</a>
A fun fact about integer division is that on x86 dividing by zero is CPU exception 0. Except, it's not just for dividing by zero, it's whenever a division is impossible to perform.<p>So, for example what happens if you divide -1 by -INT_MIN? As you probably know, Abs(INT_MIN) is larger than INT_MAX, and so it is not possible to perform -1 / INT_MIN, as well as -1LL / INT64_MIN. It will crash your program, your emulator/sandbox and your server. So, be careful!
In case divisor is always positive, you can use these variants:<p><pre><code> int divF(int a, int b) { return a / b - (a % b < 0); }
int divC(int a, int b) { return a / b + (a % b > 0); }
</code></pre>
They should be faster as it avoids branching: <a href="https://godbolt.org/z/qrraj8s6j" rel="nofollow">https://godbolt.org/z/qrraj8s6j</a>
> We could stop right here but this suffers from overflow limitations if translated into C.<p>FWIW, the final version also suffers from integer overflow limitations. If the difference between an and INT_MIN/INT_MAX (depending on whether you floor or ceil) is <= b/2, you will have integer overflow.
> transforming a float based algorithm to integers in order to make it bit-exact<p>Modern CPUs, and most programming languages, guarantee bit-exactness for floats most of the times, because they implement IEEE 754.<p>Relatively easy to break (approximate instructions like rsqrtps, FMA instructions, compiler switches like -ffast-math or /fp:fast, MXCSR rounding modes) but I think fixing bugs is probably easier than refactoring everything from FP into fixed-point.<p>BTW, multiplication/division/rounding instructions are much faster for floats. I think a fixed-point version will only be a performance win when the integers are 8 or 16 bits wide, and the algorithm is vectorizable.
I'm intensely interested in this type of stuff, but the article throws me off right away. If I were do undertake this project, I wouldn't "define round the way POSIX does" and "integer division the way C11 does". Instead I'd reinspect the choices POSIX made and the choices C11 made, and then create routines that work however you need it to, i.e. that are configurable and let you control how it works.<p>Rounding--which btw I prefer to think of as rounding to a decimal place, not rounding to an integer--for example, can introduce biases because there are 10 digits, 0 through 9, but "11 spots on the dial", from round-down-to-0 to round-up-to-0 and therefore 5 is "the exact center" and always rounding 5 in one direction is going to bias your results in one direction, depending on your dataset. The article is breezing past this stuff.<p>I'm going to keep reading because I'm sure I'll learn some interesting things, but at the end of the first page my skin is crawling because I can see ambiguities in the examples I'm being shown and I keep thinking "wut?".