Art Of Programming

musings by Dmytrii Nagirniak

Dividing Integers in C# Are Evil

If you have ever worked with arithmetical operations in C# you probably know this. But it is the thing that can easily be slept from you and not even mentioned.
What do you think the code will print? True or False?
Console.WriteLine(5/2 > 2); // True or False?
The result is, of course, FALSE. You should never forget the TYPE. Integer 5 divided by integer 2 returns INTEGER. And it is truncated integer, so the value will be 2 and not 2.5.
This fact that division operator returns INTEGER in my opinion is just wrong. There is no ANY guarantee at all that result will ever be integer. In other languages (including Pascal/Delphi) the division returns floating-point result. Which IS correct.
So in real live: INT/INT=REAL, in C# INT/INT=INT. Just wrong. No math behind such kind of division.
I have just faced this issue (just totally forgot about INT/INT=INT) trying to calculate an angle between 2 points on the Bitmap. It is simple:
Point p1 = GetIt();
Point p2 = GetIt();
var radians = Math.Atan( (p1.X-p2.X) / (p2.Y-p1.Y) ); // Atan( INT/INT)!!
As we can see the error is unavoidable. We will end up with wrong result.
So you should remember once and forever: Be explicit about type when using division.
And the code snippets should look like this to work correctly:
Console.WriteLine(5.0/2.0 > 2.0); // This  correctly becomes "True"

// casting of one division argument is enough, but better be explicit
Math.Atan( (double)(p1.X-p2.X) / (double)( p2.Y-p1.Y) ); 

// or if casting bothers you:
Math.Atan( (0.0 + p1.X-p2.X) / (0.0 + p2.Y-p1.Y) );

Additional note is that ReSharper greatly warns you saying “Possible loss of fraction”. I love it more and more every day.

Comments

Alexander
Well - to me the problem here is just in overloading the operators.

Going backwards - Pascal (hehe) has 2 different ops for wholenum division and normal one -

div
/

And there were no problems at all about the division. To me - also - this decision - to use same symbol for wholenum and normal division - was just a mistake. I have myself ran into some problems with this.
Anonymous
It's wrong to bring Significant Figures into this. SigFigs says 5/2 = 2, but 5/2.0 is also 2. SigFigs is probably only taught in engineering, chemistry and physics schools - it's not usually a topic in computer science. At any rate, it's not the right reasoning here.

Rather, I believe the real reason to simply in the hardware - Integer division is simpler and faster. Floating points are a different beast, and are slower for performance and use more energy due to the more complex circuitry involved. Difference in a single operation is microscopic at the desktop app level, but do a lot of these computations, or if you're writing for hardware, it makes a significant difference.

This is part of the reason most mobile device platforms had no support for floating point computations (if anything, they were fixed point computations emulated using integers).

In C#, double and float are floating points, and decimal is a fixed point. For historical reasons, VB differentiates the two by providing the / operator as floating point division, and the \ operator as integer division.

For better or for worse, this is how they've implemented it. Ours not to reason why; ours but to do or… yeah :-/
Dmytrii Nagirniak
In math from school 5/2 is equal to 2.5. This is not possible when the result of the division operation is always INT. So give me the math that always defines the result of the division operation equal to Integer?

In addition to that, tell me why most of other programming languages have Integer as a result of division operation?
Anonymous
I have no idea why you think IRL int/int=real, that's definitely not correct maths. Least significant number decides what the significance of the outcome will be. int = no decimals, so no decimals in the result. Back to school you go!

Comments