2

I'm coding a physical simulation and recently I was encountering anomalous results. I managed to debug my program, the error was in the division of a large double by a large int, something of the form:

cout << my_large_double/my_large_int << endl

with my_large_double of the order -10^{9} and the product of my two ints is of the order 10^{9} was returning something positive of the order 1. I fixed it by imposing a conversion to double in the denominator:

cout << my_large_double/( (double)my_large_int1*my_large_int2) << endl

But I would like to understand where is the mistake coming from, and are there ways to prevent them from happening usually?

Update: I skipped a detail that matters in my first question: the int is actually the product of two ints.

Liam
  • 593
  • 6
  • 15
  • Might be due to loopback as in the max value of int might be reached and so it looped back – Aakash Nov 26 '13 at 16:38
  • @john Experience tells me that it solved the problem, try doing it on your side if you want. – Liam Nov 26 '13 at 16:39
  • I believe Your question has been answered here: http://stackoverflow.com/questions/3051135/dividing-a-double-with-integer – Ivan Berloga Nov 26 '13 at 16:39
  • @AakashGoyal: Right int can't be larger than 2*10^9, so it should work if upgraded to int_64t, is there a way to know when you overflow a variable at running time? – Liam Nov 26 '13 at 16:40
  • What were the exact values of my_large_double and my_large_int when you tried this? What value was originally printed and what did you expect? – selbie Nov 26 '13 at 16:41
  • @john Apologies, the denominator is actually the product of two ints and so (double) is not superfluous in this case as you would have all the right to think in the previous example. – Liam Nov 26 '13 at 16:44
  • 2
    @Liam, that does make all the difference – john Nov 26 '13 at 16:45
  • try to cout the product of two ints (without cast to double) most likely it will result in overflow. – gregory561 Nov 26 '13 at 17:03

2 Answers2

4

It depends on exactly how the expression was written.

If you write this:

my_large_double / my_large_int1 / my_large_int2

then it's equivalent to:

(my_large_double / my_large_int1) / my_large_int2

which should give you reasonably accurate results; my_large_int1 is promoted to double before the first division, and my_large_int2 is promoted to double before the second division.

If you write this:

my_large_double / (my_large_int1 * my_large_int2)

then the multiplication is done in the type of the two integer variables, and depending on their values you could have an overflow (which can give you a much smaller value than the mathematical product -- though strictly speaking the behavior of signed integer overflow is undefined).

The important thing to remember is that, in most cases, each C expression is effectively evaluated in isolation; its type is not affected by the context in which it appears. The expression my_large_int1 * my_large_int2 is an integer multiplication, even if the result is the operand of a floating-point division or is assigned to a floating-point variable.

Any operation whose operands are both integers is an integer operation. If one operand is double and the other is int, the int operand is promoted to double.

Even this:

double temp = my_large_int1 * my_large_int2;
... my_large_double / temp ...

will perform an integer multiplication before using the result to initialize temp, and this:

my_large_double / (double)(my_large_int1 * my_large_int2)

has the same problem.

As you've found, the solution is to cast one or both of the integer operands to double:

my_large_double / ((double)my_large_int1 * (double)my_large_int2)

(You might as well cast both of them, just for symmetry and clarity.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
1

An IEEE format double can hold an int without precision loss up to 53 bits, versus the 31 bits typical for an int. Your solution is a good one, convert to double up front so that you don't hit an integer overflow in the multiply.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622