unsigned long long won't store big numbers - c++

I'm confused with the C/C++ unsigned long long type because theoretically it should store up to 2^64-1 which is a number of 19 decimal digits, but the following code:
unsigned int x = 1000000u; //(One million)
unsigned long long k = (x*x);
cout << k << endl;
prints out 3567587328, which is not correct.
Now 1,000,000^2 results in 1,000,000,000,000 - a number of 12 decimal digit, way below the limit of even signed long long. How could this happen?
Does it have anything to do with the system I am running? (32-bit Ubuntu)
If I need a 64 bit system to implement a 64 bit operation then another question arises:
Most compilers use linear congruential generator to generate random numbers as follow:
x(t) = (a*x(t-1) + c) mod m.
a and c is usually a 32 bit big number, m is 2^32-1
So there is a big chance that a*x(t-1) results in a 64-bit number before the modulo operation is carried out.
If a 64 bit system is needed then how could gcc generate random numbers since 1990s on 16-32bit machines?
Thanks a million.

Sure k is unsigned long long, but x is unsigned int and hence so is x*x. Your expression is calculated as an unsigned int, which results in the usual wraparound when going over the limits of unsigned types. After the damage is done, it is converted to an unsigned long long.
Possible fixes:
make x an unsigned long long
unsigned long long k = ((unsigned long long)x*(unsigned long long)x);
unsigned long long k = (1ULL*x*x);

x is unsigned int --> x*x is unsigned int as well. In case the result of the multiplication exceeds the maximal value of unsigned int, wraparound occurs. Only after these operations the result is being assigned into the receiving variable (k). If you want the result to be unsigned long long you need to promote at least one of the operand to this type, e.g.: unsigned long long k = (unsigned long long)x * x;.
Regarding your second question: compilers usually do not generate numbers, that's done during runtime. I'm not sure where did you get the formulae x(t) = (a*x(t-1) + c) mod m. Assuming this is indeed the formula there are ways to keep the intermediate results bounded: the modulo operation can be applied to any operand or intermediate result without changing the outcome. Therefore x(t) = (a*x(t-1) + c) mod m = (a mod m) * (x(t-1) mod m) + c mod m.

When you multiply an unsigned int by an unsigned int on the right side, the result is an unsigned int. As such it has the same limits as the two numbers being multiplied, regardless of the fact that this value is subsequently assigned to an unsigned long long.
However, if you cast the unsigned int variables to unsigned long long, the result will be an unsigned long long and the value will not be limited to the size of an unsigned int.
unsigned long long k = (((unsigned long long)x)*((unsigned long long)x));
That should give you the result you want.

Related

Assign a negative number to an unsigned int

This code gives the meaningful output
#include <iostream>
int main() {
unsigned int ui = 100;
unsigned int negative_ui = -22u;
std::cout << ui + negative_ui << std::endl;
}
Output:
78
The variable negative_ui stores -22, but is an unsigned int.
My question is why does unsigned int negative_ui = -22u; work.
How can an unsigned int store a negative number? Is it save to be used or does this yield undefined behaviour?
I use the intel compiler 18.0.3. With the option -Wall no warnings occurred.
Ps. I have read What happens if I assign a negative value to an unsigned variable? and Why unsigned int contained negative number
How can an unsigned int store a negative number?
It doesn't. Instead, it stores a representable number that is congruent with that negative number modulo the number of all representable values. The same is also true with results that are larger than the largest representable value.
Is it save to be used or does this yield undefined behaviour?
There is no UB. Unsigned arithmetic overflow is well defined.
It is safe to rely on the result. However, it can be brittle. For example, if you add -22u and 100ull, then you get UINT_MAX + 79 (i.e. a large value assuming unsigned long long is a larger type than unsigned) which is congruent with 78 modulo UINT_MAX + 1 that is representable in unsigned long long but not representable in unsigned.
Note that signed arithmetic overflow is undefined.
Signed/Unsigned is a convention. It uses the last bit of the variable (in case of x86 int, the last 31th bit). What you store in the variable takes the full bit length.
It's the calculations that follow that take the upper bit as a sign indicator or ignore it. Therefore, any "unsigned" variable can contain a signed value which will be converted to the unsigned form when the unsigned variable participates in a calculation.
unsigned int x = -1; // x is now 0xFFFFFFFF.
x -= 1; // x is now 0xFFFFFFFE.
if (x < 0) // false. x is compared as 0xFFFFFFFE.
int x = -1; // x stored as 0xFFFFFFFF
x -= 1; // x stored as 0xFFFFFFFE
if (x < 0) // true, x is compared as -2.
Technically valid, bad programming.

3 * 1000000000 overflows as an int, but the variable is long long. Why? [duplicate]

This question already has answers here:
long long is 8 bytes, but I get integer overflow?
(1 answer)
Why does long long n = 2000*2000*2000*2000; overflow?
(6 answers)
Closed 5 years ago.
I have a simple c++ app that performs the following calculations
long long calcOne = 3 * 100000000; // 3e8, essentially
long long calcTwo = 3 * 1000000000; // 3e9, essentially
long long calcThree = 3 * 10000000000; // 3e10, essentially
If I write the result of each calculation I get the following output:
calcOne = 300000000
calcTwo = -1294967296
calcThree = 30000000000
So why does the second calculation fail? As far as I can tell it is within the limits of a long long type (calcThree was larger...).
I am using Visual Studio 2015 on Windows 10. Thanks in advance.
Integer constants are, by default ints.
1000000000
That can fit into an int. So, this constant gets parsed as an int. But multiplying it by 3 overflows int.
10000000000
This is too big to an int, so this constant is a long long, so the resulting multiplication does not overflow.
Solution: explicitly use long long constants:
long long calcOne = 3 * 100000000LL; // 3e8, essentially
long long calcTwo = 3 * 1000000000LL; // 3e9, essentially
long long calcThree = 3 * 10000000000LL; // 3e10, essentially
What you do with a result doesn't affect how that result is calculated. So the fact that you store the result in a long long doesn't change the fact that the numbers you multiplied in the second line of code were not long longs and so they overflowed. In the third line of code, the constant is a long long, so the multiplication is performed on long longs.
The compiler saw this
long long calcOne = (int) 3 * (int) 100000000; // 3e8, essentially
long long calcTwo = (int) 3 * (int) 1000000000; // 3e9, essentially
long long calcThree = (int) 3 * (long long) 10000000000; // 3e10, essentially
And so the calcTwo right hand value was inferred as an int type and then over flowed. You see the over flow as a negative long.
long long calcOne = 3LL * 100000000LL; // 3e8, essentially
long long calcTwo = 3LL * 1000000000LL; // 3e9, essentially
long long calcThree = 3LL * 10000000000LL; // 3e10, essentially
To avoid this in the future, be explicit as to the types of your static values.To tell the compiler a number is a long long post fix it with LL.
Most programming languages rank number types by size. The size/rank/type of a numeric expression is (usually) the type of the highest-ranked value in the expression.
Example: int * double -> double
Your program has:
long long int = int * int.
What's happening is that the result of int * int is an int. So your program will multiply first and treat the result in a signed integer (maximum value ~= 2 billion, so it wraps around into negative numbers). Then, this negative value gets stored in the long long int.
300 million (your first multiplication) fits in an int. No problem there. I'm guessing the third works properly because the compiler is smart enough to know that 30 billion doesn't fit in a 32-bit int and automatically gives it a 64-bit long long int.

Squaring number in c++, Kaprekar numbers [duplicate]

This question already has answers here:
Multiplication of two integers in C++
(3 answers)
Closed 6 years ago.
Found this issue in C++ while detecting Kaprekar numbers in a range. For number 77778 -
unsigned long long sq = pow(n, 2);
returns 6,049,417,284 while
unsigned long long sq = n * n;
returns 1,754,449,988
Any ideas why? Is this some sort of overflow which pow avoids but normal n*n does not.
Assuming your n to be typical int or unsigned int, the reason for this is because
this line
unsigned long long sq = n * n;
is equivalent to
unsigned long long sq = (int)(n * n);
as the n * n will be first processed (both as integers) before assigning the result to sq. So, this is an overflow problem (And welcome to Stack Overflow too!).
You also probably want to understand these terms overflow and casting more by searching around (since they are very common issues in Computing, understanding them early will be of great help!).
This has nothing to do with Kaprekar numbers. In most of nowadays machine int is 32-bit. Thus it can only handle value -2,147,483,648 to 2,147,483,647 (or 0 to 4,294,967,295 for unsigned integer counter part).
Thus processing n * n will give you:
n * n = 6,049,417,284 - 4,294,967,296 = 1,754,449,988 //overflow at (4,294,967,295 + 1)!
If you do casting before hand:
unsigned int n = 77778;
unsigned long long sq = pow(n, 2);
unsigned long long sq2 = (unsigned long long)n * n; //note the casting here.
std::cout << sq << std::endl;
std::cout << sq2 << std::endl;
Then the results will be identical, since there won't be overflow.
Your n is declared as a 32 bit int. You need to either change it to long long or just typecast the operation into long long.
unsigned long long sq=(unsigned long long)n*n;
this will give the right answer
I suspect that n is declared as unsigned int and you've compiler with a data model that assumes int to be 32 bits wide. The maximum value that can be represented with this type would be 232 - 1 = 4294967295. Anything beyond this value would wrap around. So assigning 4294967296 would become 0, 4294967297 would become 1, and so on.
You have an overflow; since both operands are unsigned int the resulting type would be the same too. The true result of the operation would be 6049417284. Assigning it to an unsigned int would (wrap) and become 1754449988 = 6049417284 - 4294967296. This unsigned int result is assigned to a wider type unsigned long long, which doesn't change the value. It's necessary to understand the difference between the result's type (the type of the expression) and destination type (the type of the variable that is going to hold the result).
Wrap around behaviour (more formally modulo n) in unsigned types is well-defined in C++, so the compiler might not warn you.
Quote from Unsigned Arithmetic:
If an unsigned integer overflows, the result is defined modulo 2w, where w is the number of bits in that particular unsigned integer. By implication, an unsigned integer is never negative.

What if I try to assign values greater than pow(2,64)-1 to unsigned long long in c++?

If I have two unsigned long long values say pow(10,18) and pow (10,19) and I multiply them and store the output in another variable of type unsigned long long...the value which we get is obviously not the answer but does it have any logic? We get a junk type of value each time we try to this with arbitrarily large numbers, but do the outputs have any logic with the input values?
Unsigned integral types in C++ obey the rules of modular arithmetic, i.e. they represent the integers modulo 2N, where N is the number of value bits of the integral type (possibly less than its sizeof times CHAR_BIT); specifically, the type holds the values [0, 2N).
So when you multiply two numbers, the result is the remainder of the mathematical result divided by 2N.
The number N is obtainable programmatically via std::numeric_limits<T>::digits.
Yes, there's a logic.
As KerreK wrote, integers are "wrapped around" the 2N bits that constitute the width of their datatype.
To make it easy, let's consider the following:
#include <iostream>
#include <cmath>
using namespace std;
int main() {
unsigned char tot;
unsigned char ca = 200;
unsigned char ca2 = 200;
tot = ca * ca2;
cout << (int)tot;
return 0;
}
(try it: http://ideone.com/nWDYjO)
In the above example an unsigned char is 1 byte wide (max 255 decimal value), when multiplying 200 * 200 we get 40000. If we try to store it into the unsigned char it won't obviously fit.
The value is then "wrapped around", that is, tot gets the result of the following
(ca*ca2) % 256
where 256 are the bit of the unsigned char (1 byte), 28 bits
In your case you would get
(pow(10,18) * pow (10,19)) %
2number_of_bits_of_unsigned_long_long(architecture_dependent)

Weird result after assigning 2^31 to a signed and unsigned 32-bit integer variable

As the question title reads, assigning 2^31 to a signed and unsigned 32-bit integer variable gives an unexpected result.
Here is the short program (in C++), which I made to see what's going on:
#include <cstdio>
using namespace std;
int main()
{
unsigned long long n = 1<<31;
long long n2 = 1<<31; // this works as expected
printf("%llu\n",n);
printf("%lld\n",n2);
printf("size of ULL: %d, size of LL: %d\n", sizeof(unsigned long long), sizeof(long long) );
return 0;
}
Here's the output:
MyPC / # c++ test.cpp -o test
MyPC / # ./test
18446744071562067968 <- Should be 2^31 right?
-2147483648 <- This is correct ( -2^31 because of the sign bit)
size of ULL: 8, size of LL: 8
I then added another function p(), to it:
void p()
{
unsigned long long n = 1<<32; // since n is 8 bytes, this should be legal for any integer from 32 to 63
printf("%llu\n",n);
}
On compiling and running, this is what confused me even more:
MyPC / # c++ test.cpp -o test
test.cpp: In function ‘void p()’:
test.cpp:6:28: warning: left shift count >= width of type [enabled by default]
MyPC / # ./test
0
MyPC /
Why should the compiler complain about left shift count being too large? sizeof(unsigned long long) returns 8, so doesn't that mean 2^63-1 is the max value for that data type?
It struck me that maybe n*2 and n<<1, don't always behave in the same manner, so I tried this:
void s()
{
unsigned long long n = 1;
for(int a=0;a<63;a++) n = n*2;
printf("%llu\n",n);
}
This gives the correct value of 2^63 as the output which is 9223372036854775808 (I verified it using python). But what is wrong with doing a left shit?
A left arithmetic shift by n is equivalent to multiplying by 2n
(provided the value does not overflow)
-- Wikipedia
The value is not overflowing, only a minus sign will appear since the value is 2^63 (all bits are set).
I'm still unable to figure out what's going on with left shift, can anyone please explain this?
PS: This program was run on a 32-bit system running linux mint (if that helps)
On this line:
unsigned long long n = 1<<32;
The problem is that the literal 1 is of type int - which is probably only 32 bits. Therefore the shift will push it out of bounds.
Just because you're storing into a larger datatype doesn't mean that everything in the expression is done at that larger size.
So to correct it, you need to either cast it up or make it an unsigned long long literal:
unsigned long long n = (unsigned long long)1 << 32;
unsigned long long n = 1ULL << 32;
The reason 1 << 32 fails is because 1 doesn't have the right type (it is int). The compiler doesn't do any converting magic before the assignment itself actually happens, so 1 << 32 gets evaluated using int arithmic, giving a warning about an overflow.
Try using 1LL or 1ULL instead which respectively have the long long and unsigned long long type.
The line
unsigned long long n = 1<<32;
results in an overflow, because the literal 1 is of type int, so 1 << 32 is also an int, which is 32 bits in most cases.
The line
unsigned long long n = 1<<31;
also overflows, for the same reason. Note that 1 is of type signed int, so it really only has 31 bits for the value and 1 bit for the sign. So when you shift 1 << 31, it overflows the value bits, resulting in -2147483648, which is then converted to an unsigned long long, which is 18446744071562067968. You can verify this in the debugger, if you inspect the variables and convert them.
So use
unsigned long long n = 1ULL << 31;