Madeleine P. Vincent
Madeleine P. Vincent

Reputation: 3621

A C++ large integer precision question during multiplication

If I run the following program:

#include <iostream>

int main()
{
   using namespace std;

   uint64_t f12 = 18446744073709551568;
   uint64_t f3 = 2;
   uint64_t f123 = f12 * f3;

   cout << f12 << endl;
   cout << f3 << endl;
   cout << f123 << endl;

   return 0;

}

I get as output:

18446744073709551568
2
18446744073709551520

I don't understand why 2 times f12 results in a value that is less (by exactly 48). If the value rolled over due to reaching the size of the uint64 value, wouldn't it be quite different (unless this is an extreme coincidence)?

Upvotes: 1

Views: 89

Answers (3)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275200

The shifting is a red herring.

64 bit unsigned math in C++ is math modulo 2 to the power 64. If 2*a is 48 less than a, then a is 2 to the power 64 minus 48.

Upvotes: 0

Stephan Lechner
Stephan Lechner

Reputation: 35154

Multiplying an integral value by 2 can be seen as a left shift of the bits. When you convert your number 18446744073709551568 to binary, then this is...

1111111111111111111111111111111111111111111111111111111111010000

If you shift these bits one left, then the result is...

1111111111111111111111111111111111111111111111111111111110100000

In the least significant byte, i.e. at the right end, 11010000 (decimal 208) is replaced by 10100000 (decimal 160), which is exactly your 48 less. All the higher significant bytes remain the same. So the overall result is 48 less, too.

Upvotes: 1

Sam Varshavchik
Sam Varshavchik

Reputation: 118292

You can chalk it up to "extreme coincidence". 18446744073709551568 in binary is

FFFFFFFFFFFFFFD0

We all discovered when we learned binary math that multiplication by two is equivalent to a left shift, which becomes:

FFFFFFFFFFFFFFA0

Note that D0 is

11010000

in binary, with the high bit set, so shifting left the lower 8 bits becomes

10100000

or A0 (with the high bit getting carried left).

And now, by computing what's FFFFFFFFFFFFFFA0 in decimal you'll get the answer to your question (you are kind of getting a clue already, since A0 is less than D0 by 30 hexadecimal, which happens to be, purely by accident, 48).

Upvotes: 3

Related Questions