Question

I am trying to run the below program in 32 bit Linux platform.

    int main()
    {
         unsigned long long  val  = 0;
         val   = 140417 * 100000 + 92 + 1;
    }

The output is some garbage value (1156798205).

After some research, I found that :here

 long long size: 64 bits (MAX VALUE: signed long long = 144115188075855871, unsigned long long = 1073741823) 

The above code is giving the same problem with Visual Studio 2005 for both the datatypes unsigned long long and signed long long.

But as per the MSDN documentation: here

unsigned long long  8 byte  range of values  0 to 18,446,744,073,709,551,615

I am wondering how to handle large range of values in 32 bit Linux platform using the C++ program.

Thanks for you help.

Was it helpful?

Solution 2

The problem is that although you are using a 64bit data type, your calculations are using 32bit values, so you are encountering integer overflow. 140417 * 100000 is 14041700000 (0x344F356A0) in 64bit, but is 1156798112 (0x44F356A0) in 32bit. As you can see, 0x300000000 is being truncated off of the result, as it does not fit in a 32bit value.

You need to ensure that you are using 64bit calculations, eg:

typedef unsigned long long ulong64_t;

int main()
{
     ulong64_t val = 0;
     val = ulong64_t(140417) * ulong64_t(100000) + 92 + 1;
}

Alternatively, use integer constant suffixes:

int main()
{
     unsigned long long val = 0;
     val = 140417i64 * 100000i64 + 92 + 1;
}

Or:

int main()
{
     unsigned long long val = 0;
     val = 140417ull * 100000ull + 92 + 1;
}

OTHER TIPS

The problem is that the type of an unsuffixed integer constant (like 42) is the smallest of int, long int, long long int that can hold its value, and the type of an expression is determined by the expression itself, not by the context in which it appears.

So if int happens to be 32 bits on your system, then in this:

unsigned long long val = 140417 * 100000 + 92 + 1;

the constants 140417 and 100000 (which both fit in 32 bits) are of type int, and the multiplication is a 32-bit multiplication -- which overflows because the product of those two numbers doesn't fit in 32 bits. (The type of a standalone literal is adjusted based on its value; the type of a larger expression is not.)

The most straightforward way to avoid this is to use constants of type unsigned long long:

unsigned long long val = 140417ULL * 100000ULL + 92ULL + 1ULL;

(It happens that not all the ULL suffixes are necessary, but it doesn't hurt to apply them to all the constants in the expression.)

If you print out: sizeof(unsigned long long), the max is 2^(that value)-1.

I am wondering how to handle large range of values in 32 bit Linux platform using the C++ program.

Add #include <stdint.h> and use explicit long long or preferably int64_t or uint64_t types.

Recent GCC (e.g. GCC 4.9 which is released now in mid-april 2014) may have __int128.

If you want to handle very large numbers (bigger than 263 in absolute value), so called bignums you'll need a bignum library (like GMPlib), or a language supporting them natively (e.g. Common Lisp, using SBCL ....)

BTW, the following program

#include <stdio.h>
int main () {
  unsigned long long val = 0;
  val = 140417 * 100000LL + 92 + 1;
  printf ("val=%lld\n", val);
  return 0;
}

does work as you expect on Linux x86 32 bits. If you omit the LL suffix for 100000 (suffix LL needed to get a long long literal 100000 constant) you'll get a warning integer overflow in expressionat compile time with gcc -Wall hpfe.c -o hpfe ....

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top