-1

When I tried this multiplication compiler gave an integer overflow error

int main(){
    long long int x;
    x = 55201 * 55201;
    printf("%lld", x);
    return 0;
}

But When i do the same operation with pow() function i do not get any error.

int main(){
    long long int x;
    x = pow(55201, 2);
    printf("%lld", x);
    return 0;
}

Why is that so? I must use the first code.

Filburt
  • 17,626
  • 12
  • 64
  • 115
gg1810
  • 19
  • 3
  • 1
    Use `long unsigned int` this should just do. There are platforms which even for `long long` integers just provide 32 bits. – alk Mar 29 '16 at 16:34
  • 1
    `55201 * 55201` is evaluated *by the compiler* and gives the warning *"integral constant overflow"*. If you qualify the operands, that will work. `55201LL * 55201LL`. – Weather Vane Mar 29 '16 at 16:41
  • @WeatherVane: Wouldn't this fail as well if `long long` were 32 bits wide only? – alk Mar 29 '16 at 16:45
  • @alk if you say so: I thought `long` was minimum 32 bits, giving the need for `long long` minimum 64 bits. – Weather Vane Mar 29 '16 at 16:46
  • @WeatherVane: On ancient (>20 year?) 32 bit boxes there simply are no 64bit integers. – alk Mar 29 '16 at 16:47
  • 1
    @alk, but as you infer, the product is within the range of `uint32_t`. – Weather Vane Mar 29 '16 at 16:47
  • So one perhaps better used `55201LU * ...`. – alk Mar 29 '16 at 16:48
  • @alk: `long` is not guaranteed to have more than 32 bits (see Windows and POSIX32). And `long long` is guaranteed to have 64 bits at least. Of course this is according to the standard. There is no use in accounting for ancient compilers unless specifically asked. The C tag is about standard C. – too honest for this site Mar 29 '16 at 17:04
  • Sure, sure. However `55201UL* 55201UL` fits in a 32 bit unsigned integer, no need for `long long` at all here. @Olaf – alk Mar 29 '16 at 17:07
  • @alk Correct - it fits in 32 bit unsigned but why not simply use the type of the destination? The calculation won't be done at run time anyway so using the destination type seems as clear as it gets IMO. – Support Ukraine Mar 29 '16 at 17:19
  • @alk: Correct, but using signed has other implications, e.g. overflow being UB. – too honest for this site Mar 29 '16 at 17:29
  • @Olaf: Err "*signed*"? Who is talking about "*signed*"? – alk Mar 29 '16 at 17:35
  • @alk: Oh, I thought OP does. IIreadC, He states he has to "use the first code", which I read as if he cannot change to `unsigned long`. Maybe I'm wrong, though. – too honest for this site Mar 29 '16 at 18:09

4 Answers4

3

You need to change your code like this

int main(){
    long long int x;
    x = 55201LL * 55201LL;  // <--- notice the LL
    printf("%lld", x);
    return 0;
}

to make the multiplication done as long long

When you use the pow function you don't see any problems because pow uses floating point for calculations.

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
  • Didn't remember the LL prefix. Nice! – Lauro Moura Mar 29 '16 at 16:45
  • i didn't know that we can capable of doing something like that thanks. – gg1810 Mar 29 '16 at 16:48
  • 1
    @gg1810 It is always important to consider how the RHS calculation is done and whether it matches the LHS type. If you search for `implicit conversion` and `integer promotion` you'll get a lot of hits. Here is one: http://stackoverflow.com/questions/6770258/how-do-promotion-rules-work-when-the-signedness-on-either-side-of-a-binary-opera – Support Ukraine Mar 29 '16 at 17:01
1

Here (Linux 64bits, gcc 5.2.1), 55201 is an integer literal of size 4, and the expression 55201 * 55201 seems to be stored in an integer of size 4 before being assigned to your long long int.

One option is storing the factor in another variable before multiplying, to increase the range.

int main(){
  long long int x, factor;
  factor = 55201;
  x = factor * factor;
  printf("%lld", x);
  return 0;
}
Lauro Moura
  • 750
  • 5
  • 15
1

In below code 55201 is taken as integer by default and then multiplied and result will also be an integer after multiplying. During code optimization phase multiplication is going to be calculated but then it seems to overflow the integer limit...That's why compiler generates the warning i.e. integer overflow

int main(){
    long long int x;
    x = 55201 * 55201;
    printf("%lld", x);
    return 0;
}

Declaration of pow is as:

double pow(double x, double y);

But in second case function pow take every arguments as double so now "55201" and "2" will be implicitly cast as double and now calculation takes place on the double precision so after calculation result will not cross the limit for double type...And hence the compiler will not generate any overflow message in this case.

To establish same result but using method 1 can be done as:

long long int result, number;
number = 55201;
result = number * number;
// Print result as..
printf("%lld\n", result);

That's it.. Was it helpful to understand...

Shiv
  • 122
  • 2
  • 16
0

Problem is the operation is performed with the largest type of the operands, at least int (C standard, 6.3.1.8). The assignment is just another expression in C and the type of the left hand side of the = is irrelevant for the right hand side operation.

On your platform, both constants fit into an int, so the expression 55201 * 55201 is evaluated as int. Problem is the result does not fit into an int, thus generates an overflow.

Signed integer overflow is undefined behaviour. This means everything can happen. Luckily your compiler is clever enough to detect this and warn you instead of the computer jumping out of the window. Briefly: avoid it!

Solution is to perform the operation with a type which can hold the full result. A short calculation yields that the product requires 32 bits to represent the value. Thus an unsigned long would be sufficient. If you want a signed integer, you need another bit for the sign, i.e. 33 bits. Such a type is very rare nowadays, so you have to use a long long which has at least 64 bits. (Don't feel tempted to use long, even iff it has 64 bits on your platform; this makes your code implementation defined, thus non-portable without any benefit.)

For this, you need at least one of the operands to have the type of the result type:

x = 55201LL * 55201;   // first factor is a long long constant

If variables are involved use a cast:

long f1 = 55201;      // an int is not guaranteed to hold this value!
x = (long long)f1 * 55201;

Note not using L suffix for the constants here. They will automatically be promoted to the smallest type (int at least) which can represent the value.


The other expression x = pow(55201, 2) uses a floating point function. Thus the arguments are converted to double before pow is called. The double result is converted by the assignment operator to the left hand side type.

This has two problems:

  1. A double is not guaranteed to have a mantissa of 63 bits (excluding sign) like a long long. The common IEEE754 implementations have this problem. (This is not relevant for this specific calculation)
  2. All floating point arithmetic may include rounding errors, so the result might deviate from the exactly result. That's why you have to use the first version.

As a general rule one should never use floating point arithmetic if an exact result is required. And mixing floating point and integer should be done very cautiously.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52