You are on page 1of 2

Double-checking variable types to prevent overflow Title: Double-checking variable types to prevent overflow Problem: When solving algorithm

problems on TopCoder that are related to number calculation, variable types must be chosen carefully enough to prevent overflow. On some problems, it is obvious for us to choose the right type, but for others, it is not, especially on problems that have many intermediate calculation steps before getting final result. Solution: Below are some general tips to prevent this kind of error: -Examine data types of input and output variables, list operations required and determine types for intermediate results. -Remember approximate boundary values for popular types in your language: for example, int is about -2,000,000,000 to 2,000,000,000 and long is about -9,000,000,000,000,000,000 to 9,000,000,000,000,000,000 in Java. So, if a result is expected to be larger than 2,000,000,000 then it is better to use a long data type for it. -Walk-through each calculation steps, check with boundary cases to see how much the result may be, especially on steps that have addition and/or multiplication operations. -Remember when auto-type casting happen (and when not happen) on your language. For example: if "result" is of type long, "num1" and "num2" are of type int, then this expression: result = num1 + num2 will produce a wrong result if "num1" plus "num2" larger than maximum int value. Although "result" is a long, "(num1 + num2)" is not (it is still an int). 2 examples below are my own solutions on TC SRM problems which are fail because of overflow 1/Problem FeudaliasBattle on Single Round Match 438 Round 1 - Division II, Level Two This is my code to calculate the distance between 2 points double d(int x1, int y1, int x2, int y2){ return 1.0*Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); } Because x[1], x[2], y[1] and y[2] can range from 0 and 1000000, so (x1-x2)*(x1-x2) and (y1-y2)*(y1-y2) can individually overflow. To solve it correctly, cast x1, x2, y1, and y1 to long. 2/Problem Multifactorial on Single Round Match 335 Round 1 - Division II, Level Two This problem requires calculating a number to see if it is less than or equal to 1000000000000000000 or not. My code to check the number is: private long fac(int n,int k) throws Exception{ long t=1; while(n>=1) { t=t*n; if(t>Math.pow(10,18)) throw new Exception(); n=n-k; } return t; } The problem is at the line t=t*n; because t*n maybe larger than maximum long value, t will now contain wrong value. To solve it correctly, change t data type to double. Good recipe. Perhaps it can be merged with "detecting overflow"? I am thinking something like this Suppose A and B are two ints. To check whether A+B overflows in Java:

if (A > 0 && B > 0 && A > Integer.MAX_VALUE - B) // overflows to above Integer.MAX_VALUE else if (A < 0 && B < 0 && A < Integer.MIN_VALUE - B) // overflows to below Integer.MIN_VALUE

else // does not overflow

To check whether A*B overflows in Java:

if (A/B >= 0 && Math.abs(A) > Math.abs(Integer.MAX_VALUE*1.0/B)) // A and B have the same sign. Overflows to above Integer.MAX_VALUE else if (A/B <= 0 && Math.abs(A) > Math.abs(Integer.MIN_VALUE*1.0/B)) // A and B has opposite sign. Overflows to belove Integer.MIN_VALUE else // does not overflow

Make sure you include (*1.0) to avoid integer division. In c# integer overflows can be detected using the keyword "checked" like this: try { C = checked(A + B); } catch (System.OverflowException e) { // A + B produced overflow System.Console.WriteLine(e.ToString()); } // A + B didn't produce overflow Also, it should be pointed out that overflow is not always a bad thing. In many cases overflow is just a modulo 2^32 operation. Another idea is to cast integers to longs and then perform the check. To check whether A*B overflows in Java:

long prod=1L*A*B; if (prod > Integer.MAX_VALUE || prod < Integer.MIN_VALUE) //overflows

Also I am wondering whether you can get away with just this:

if (A*B/B != A) //overflows Can anyone break it? EDIT: for some reasons when I write 1L inside java brackets, the "L" disappears. Petr used this trick in the past: You can also make all arithmetic operations checked by default, when You use local testing. In Visual Studio 2005 express it is: Project=>properties=>build=>advanced=>check for arithmetic overflow/underflow. //Before multiplying A by B: if(MAX_INTEGER/B<A) // overflows That only works if A and B are positive...

You might also like