C++: Large integer values [duplicate] - c++

Can unsigned long int hold a ten digits number (1,000,000,000 - 9,999,999,999) on a 32-bit computer?
Additionally, what are the ranges of unsigned long int , long int, unsigned int, short int, short unsigned int, and int?

The minimum ranges you can rely on are:
short int and int: -32,767 to 32,767
unsigned short int and unsigned int: 0 to 65,535
long int: -2,147,483,647 to 2,147,483,647
unsigned long int: 0 to 4,294,967,295
This means that no, long int cannot be relied upon to store any 10-digit number. However, a larger type, long long int, was introduced to C in C99 and C++ in C++11 (this type is also often supported as an extension by compilers built for older standards that did not include it). The minimum range for this type, if your compiler supports it, is:
long long int: -9,223,372,036,854,775,807 to 9,223,372,036,854,775,807
unsigned long long int: 0 to 18,446,744,073,709,551,615
So that type will be big enough (again, if you have it available).
A note for those who believe I've made a mistake with these lower bounds: the C requirements for the ranges are written to allow for ones' complement or sign-magnitude integer representations, where the lowest representable value and the highest representable value differ only in sign. It is also allowed to have a two's complement representation where the value with sign bit 1 and all value bits 0 is a trap representation rather than a legal value. In other words, int is not required to be able to represent the value -32,768.

The size of the numerical types is not defined in the C++ standard, although the minimum sizes are. The way to tell what size they are on your platform is to use numeric limits
For example, the maximum value for a int can be found by:
std::numeric_limits<int>::max();
Computers don't work in base 10, which means that the maximum value will be in the form of 2n-1 because of how the numbers of represent in memory. Take for example eight bits (1 byte)
0100 1000
The right most bit (number) when set to 1 represents 20, the next bit 21, then 22 and so on until we get to the left most bit which if the number is unsigned represents 27.
So the number represents 26 + 23 = 64 + 8 = 72, because the 4th bit from the right and the 7th bit right the left are set.
If we set all values to 1:
11111111
The number is now (assuming unsigned)
128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = 255 = 28 - 1
And as we can see, that is the largest possible value that can be represented with 8 bits.
On my machine and int and a long are the same, each able to hold between -231 to 231 - 1. In my experience the most common size on modern 32 bit desktop machine.

To find out the limits on your system:
#include <iostream>
#include <limits>
int main(int, char **) {
std::cout
<< static_cast< int >(std::numeric_limits< char >::max()) << "\n"
<< static_cast< int >(std::numeric_limits< unsigned char >::max()) << "\n"
<< std::numeric_limits< short >::max() << "\n"
<< std::numeric_limits< unsigned short >::max() << "\n"
<< std::numeric_limits< int >::max() << "\n"
<< std::numeric_limits< unsigned int >::max() << "\n"
<< std::numeric_limits< long >::max() << "\n"
<< std::numeric_limits< unsigned long >::max() << "\n"
<< std::numeric_limits< long long >::max() << "\n"
<< std::numeric_limits< unsigned long long >::max() << "\n";
}
Note that long long is only legal in C99 and in C++11.

Other folks here will post links to data_sizes and precisions, etc.
I'm going to tell you how to figure it out yourself.
Write a small application that will do the following.
unsigned int ui;
std::cout << sizeof(ui));
This will (depending on compiler and architecture) print 2, 4 or 8, saying 2 bytes long, 4 bytes long, etc.
Let’s assume it's 4.
You now want the maximum value 4 bytes can store, the maximum value for one byte is (in hexadecimal) 0xFF. The maximum value of four bytes is 0x followed by 8 f's (one pair of f's for each byte, and the 0x tells the compiler that the following string is a hex number). Now change your program to assign that value and print the result:
unsigned int ui = 0xFFFFFFFF;
std::cout << ui;
that’s the maximum value an unsigned int can hold, shown in base 10 representation.
Now do that for long's, shorts and any other INTEGER value you're curious about.
NB: This approach will not work for floating point numbers (i.e. double or float).

In C++, now int and other data is stored using the two's complement method.
That means the range is:
-2147483648 to 2147483647
or -2^31 to 2^31-1.
1 bit is reserved for 0 so positive value is one less than 2^(31).

You can use the numeric_limits<data_type>::min() and numeric_limits<data_type>::max() functions present in limits header file and find the limits of each data type.
#include <iostream>
#include <limits>
using namespace std;
int main()
{
cout<<"Limits of Data types:\n";
cout<<"char\t\t\t: "<<static_cast<int>(numeric_limits<char>::min())<<" to "<<static_cast<int>(numeric_limits<char>::max())<<endl;
cout<<"unsigned char\t\t: "<<static_cast<int>(numeric_limits<unsigned char>::min())<<" to "<<static_cast<int>(numeric_limits<unsigned char>::max())<<endl;
cout<<"short\t\t\t: "<<numeric_limits<short>::min()<<" to "<<numeric_limits<short>::max()<<endl;
cout<<"unsigned short\t\t: "<<numeric_limits<unsigned short>::min()<<" to "<<numeric_limits<unsigned short>::max()<<endl;
cout<<"int\t\t\t: "<<numeric_limits<int>::min()<<" to "<<numeric_limits<int>::max()<<endl;
cout<<"unsigned int\t\t: "<<numeric_limits<unsigned int>::min()<<" to "<<numeric_limits<unsigned int>::max()<<endl;
cout<<"long\t\t\t: "<<numeric_limits<long>::min()<<" to "<<numeric_limits<long>::max()<<endl;
cout<<"unsigned long\t\t: "<<numeric_limits<unsigned long>::min()<<" to "<<numeric_limits<unsigned long>::max()<<endl;
cout<<"long long\t\t: "<<numeric_limits<long long>::min()<<" to "<<numeric_limits<long long>::max()<<endl;
cout<<"unsiged long long\t: "<<numeric_limits<unsigned long long>::min()<<" to "<<numeric_limits<unsigned long long>::max()<<endl;
cout<<"float\t\t\t: "<<numeric_limits<float>::min()<<" to "<<numeric_limits<float>::max()<<endl;
cout<<"double\t\t\t: "<<numeric_limits<double>::min()<<" to "<<numeric_limits<double>::max()<<endl;
cout<<"long double\t\t: "<<numeric_limits<long double>::min()<<" to "<<numeric_limits<long double>::max()<<endl;
}
The output will be:
Limits of Data types:
char : -128 to 127
unsigned char : 0 to 255
short : -32768 to 32767
unsigned short : 0 to 65535
int : -2147483648 to 2147483647
unsigned int : 0 to 4294967295
long : -2147483648 to 2147483647
unsigned long : 0 to 4294967295
long long : -9223372036854775808 to 9223372036854775807
unsigned long long : 0 to 18446744073709551615
float : 1.17549e-038 to 3.40282e+038
double : 2.22507e-308 to 1.79769e+308
long double : 3.3621e-4932 to 1.18973e+4932

For an unsigned data type, there isn't any sign bit and all bits are for data ; whereas for a signed data type, MSB is indicating a sign bit and the remaining bits are for data.
To find the range, do the following things:
Step 1: Find out number of bytes for the given data type.
Step 2: Apply the following calculations.
Let n = number of bits in data type
For signed data type ::
Lower Range = -(2^(n-1))
Upper Range = (2^(n-1)) - 1)
For unsigned data type ::
Lower Range = 0
Upper Range = (2^(n)) - 1
For example,
For unsigned int size = 4 bytes (32 bits) → Range [0, (2^(32)) - 1]
For signed int size = 4 bytes (32 bits) → Range [-(2^(32-1)), (2^(32-1)) - 1]

No, only part of ten digits number can be stored in a unsigned long int whose valid range is 0 to 4,294,967,295.
You can refer to this:
http://msdn.microsoft.com/en-us/library/s3f49ktz(VS.80).aspx

Can unsigned long int hold a ten digits number (1,000,000,000 - 9,999,999,999) on a 32-bit computer.
No

You should look at the specialisations of the numeric_limits<> template for a given type. It’s in the <limits> header.

Related

Wrap around range of unsigned int in C++?

I am going through C++ Primer 5th Edition and am currently doing the signed/unsigned section. A quick question I have is when there is a wrap-around, say, in this block of code:
unsigned u = 10;
int i = -42;
std::cout << i + i << std::endl; // prints -84
std::cout << u + i << std::endl; // if 32-bit ints, prints 4294967264
I thought that the max range was 4294967295 with the 0 being counted, so I was wondering why the wrap-around seems to be done from 4294967296 in this problem.
Unsigned arithmetic is modulo (maximum value of the type plus 1).
If maximum value of an unsigned is 4294967295 (2^32 - 1), the result will be mathematically equal to (10-42) modulo 4294967296 which equals 10-42+4294967296 i.e. 4294967264
When an out-of-range value is converted to an unsigned type, the result is the remainder of it modulo the number of values the target unsigned type can hold. For instance, the result of n converted to unsigned char is n % 256, because unsigned char can hold values 0 to 255.
It's similar in your example, the wrap-around is done using 4294967296, the number of values that a 32-bit unsigned integer can hold.
Given unsigned int that is 32 bits you're correct that the range is [0, 4294967295].
Therefore -1 is 4294967295. Which is logically equivalent to 4294967296 - 1 which should explain the behavior you're seeing.

How to set, clear a bit of a long long int number in C/C++?

I want to set bit in a long long int number on a 64 bit machine.
Example, i want to set bit at element 18 19, i use the following code:
A1 |= 1 << 2 * i; // i = 9 , set bit 18 =1, A1 long long int
A1 &= ~(1 << 2 * i + 1); //clear bit 19 = 0
but it doesn't work. If i do it for long int, it works fine.
The literal 1 has type int, which is probably smaller than long long. You'll get undefined behaviour (typically a value of zero) if you shift by enough bits to overflow the int type; and the second line will (probably) clear any bits present in A1 but not in an int value.
Use 1LL to specify a long long type, or decltype(A1)(1) to specify a type that matches A1.
In general, it's usually best to use unsigned types (unsigned long long or perhaps uint64_t in this case) for bit-wrangling. Use 1ULL to get a literal of type unsigned long long.

c/c++ left shift unsigned vs signed

I have this code.
#include <iostream>
int main()
{
unsigned long int i = 1U << 31;
std::cout << i << std::endl;
unsigned long int uwantsum = 1 << 31;
std::cout << uwantsum << std::endl;
return 0;
}
It prints out.
2147483648
18446744071562067968
on Arch Linux 64 bit, gcc, ivy bridge architecture.
The first result makes sense, but I don't understand where the second number came from. 1 represented as a 4byte int signed or unsigned is
00000000000000000000000000000001
When you shift it 31 times to the left, you end up with
10000000000000000000000000000000
no? I know shifting left for positive numbers is essentially 2^k where k is how many times you shift it, assuming it still fits within bounds. Why is it I get such a bizarre number?
Presumably you're interested in why this: unsigned long int uwantsum = 1 << 31; produces a "strange" value.
The problem is pretty simple: 1 is a plain int, so the shift is done on a plain int, and only after it's complete is the result converted to unsigned long.
In this case, however, 1<<31 overflows the range of a 32-bit signed int, so the result is undefined1. After conversion to unsigned, the result remains undefined.
That said, in most typical cases, what's likely to happen is that 1<<31 will give a bit pattern of 10000000000000000000000000000000. When viewed as a signed 2's complement2 number, this is -2147483648. Since that's negative, when it's converted to a 64-bit type, it'll be sign extended, so the top 32 bits will be filled with copies of what's in bit 31. That gives: 1111111111111111111111111111111110000000000000000000000000000000 (33 1-bits followed by 31 0-bits).
If we then treat that as an unsigned 64-bit number, we get 18446744071562067968.
§5.8/2:
The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are zero-filled. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. Otherwise, if E1 has a signed type and non-negative value, and E1×2E2 is representable in the corresponding unsigned type of the result type, then that value, converted to the result type, is the resulting value; otherwise, the behavior is undefined.
In theory, the computer could use 1's complement or signed magnitude for signed numbers--but 2's complement is currently much more common than either of those. If it did use one of those, we'd expect a different final result.
The literal 1 with no U is a signed int, so when you shift << 31, you get integer overflow, generating a negative number (under the umbrella of undefined behavior).
Assigning this negative number to an unsigned long causes sign extension, because long has more bits than int, and it translates the negative number into a large positive number by taking its modulus with 264, which is the rule for signed-to-unsigned conversion.
It's not "bizarre".
Try printing the number in hex and see if it's any more recognizable:
std::cout << std::hex << i << std::endl;
And always remember to qualify your literals with "U", "L" and/or "LL" as appropriate:
http://en.cppreference.com/w/cpp/language/integer_literal
unsigned long long l1 = 18446744073709550592ull;
unsigned long long l2 = 18'446'744'073'709'550'592llu;
unsigned long long l3 = 1844'6744'0737'0955'0592uLL;
unsigned long long l4 = 184467'440737'0'95505'92LLU;
I think it is compiler dependent .
It gives same value
2147483648
2147483648
on my machiene (g++) .
Proof : http://ideone.com/cvYzxN
And if overflow is there , then because uwantsum is unsigned long int and unsigned values are ALWAYS positive , conversion is done from signed to unsigned by using (uwantsum)%2^64 .
Hope this helps !
Its in the way you printed it out.
using formar specifier %lu should represent a proper long int

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;

What range of values can integer types store in C++?

Can unsigned long int hold a ten digits number (1,000,000,000 - 9,999,999,999) on a 32-bit computer?
Additionally, what are the ranges of unsigned long int , long int, unsigned int, short int, short unsigned int, and int?
The minimum ranges you can rely on are:
short int and int: -32,767 to 32,767
unsigned short int and unsigned int: 0 to 65,535
long int: -2,147,483,647 to 2,147,483,647
unsigned long int: 0 to 4,294,967,295
This means that no, long int cannot be relied upon to store any 10-digit number. However, a larger type, long long int, was introduced to C in C99 and C++ in C++11 (this type is also often supported as an extension by compilers built for older standards that did not include it). The minimum range for this type, if your compiler supports it, is:
long long int: -9,223,372,036,854,775,807 to 9,223,372,036,854,775,807
unsigned long long int: 0 to 18,446,744,073,709,551,615
So that type will be big enough (again, if you have it available).
A note for those who believe I've made a mistake with these lower bounds: the C requirements for the ranges are written to allow for ones' complement or sign-magnitude integer representations, where the lowest representable value and the highest representable value differ only in sign. It is also allowed to have a two's complement representation where the value with sign bit 1 and all value bits 0 is a trap representation rather than a legal value. In other words, int is not required to be able to represent the value -32,768.
The size of the numerical types is not defined in the C++ standard, although the minimum sizes are. The way to tell what size they are on your platform is to use numeric limits
For example, the maximum value for a int can be found by:
std::numeric_limits<int>::max();
Computers don't work in base 10, which means that the maximum value will be in the form of 2n-1 because of how the numbers of represent in memory. Take for example eight bits (1 byte)
0100 1000
The right most bit (number) when set to 1 represents 20, the next bit 21, then 22 and so on until we get to the left most bit which if the number is unsigned represents 27.
So the number represents 26 + 23 = 64 + 8 = 72, because the 4th bit from the right and the 7th bit right the left are set.
If we set all values to 1:
11111111
The number is now (assuming unsigned)
128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = 255 = 28 - 1
And as we can see, that is the largest possible value that can be represented with 8 bits.
On my machine and int and a long are the same, each able to hold between -231 to 231 - 1. In my experience the most common size on modern 32 bit desktop machine.
To find out the limits on your system:
#include <iostream>
#include <limits>
int main(int, char **) {
std::cout
<< static_cast< int >(std::numeric_limits< char >::max()) << "\n"
<< static_cast< int >(std::numeric_limits< unsigned char >::max()) << "\n"
<< std::numeric_limits< short >::max() << "\n"
<< std::numeric_limits< unsigned short >::max() << "\n"
<< std::numeric_limits< int >::max() << "\n"
<< std::numeric_limits< unsigned int >::max() << "\n"
<< std::numeric_limits< long >::max() << "\n"
<< std::numeric_limits< unsigned long >::max() << "\n"
<< std::numeric_limits< long long >::max() << "\n"
<< std::numeric_limits< unsigned long long >::max() << "\n";
}
Note that long long is only legal in C99 and in C++11.
Other folks here will post links to data_sizes and precisions, etc.
I'm going to tell you how to figure it out yourself.
Write a small application that will do the following.
unsigned int ui;
std::cout << sizeof(ui));
This will (depending on compiler and architecture) print 2, 4 or 8, saying 2 bytes long, 4 bytes long, etc.
Let’s assume it's 4.
You now want the maximum value 4 bytes can store, the maximum value for one byte is (in hexadecimal) 0xFF. The maximum value of four bytes is 0x followed by 8 f's (one pair of f's for each byte, and the 0x tells the compiler that the following string is a hex number). Now change your program to assign that value and print the result:
unsigned int ui = 0xFFFFFFFF;
std::cout << ui;
that’s the maximum value an unsigned int can hold, shown in base 10 representation.
Now do that for long's, shorts and any other INTEGER value you're curious about.
NB: This approach will not work for floating point numbers (i.e. double or float).
In C++, now int and other data is stored using the two's complement method.
That means the range is:
-2147483648 to 2147483647
or -2^31 to 2^31-1.
1 bit is reserved for 0 so positive value is one less than 2^(31).
You can use the numeric_limits<data_type>::min() and numeric_limits<data_type>::max() functions present in limits header file and find the limits of each data type.
#include <iostream>
#include <limits>
using namespace std;
int main()
{
cout<<"Limits of Data types:\n";
cout<<"char\t\t\t: "<<static_cast<int>(numeric_limits<char>::min())<<" to "<<static_cast<int>(numeric_limits<char>::max())<<endl;
cout<<"unsigned char\t\t: "<<static_cast<int>(numeric_limits<unsigned char>::min())<<" to "<<static_cast<int>(numeric_limits<unsigned char>::max())<<endl;
cout<<"short\t\t\t: "<<numeric_limits<short>::min()<<" to "<<numeric_limits<short>::max()<<endl;
cout<<"unsigned short\t\t: "<<numeric_limits<unsigned short>::min()<<" to "<<numeric_limits<unsigned short>::max()<<endl;
cout<<"int\t\t\t: "<<numeric_limits<int>::min()<<" to "<<numeric_limits<int>::max()<<endl;
cout<<"unsigned int\t\t: "<<numeric_limits<unsigned int>::min()<<" to "<<numeric_limits<unsigned int>::max()<<endl;
cout<<"long\t\t\t: "<<numeric_limits<long>::min()<<" to "<<numeric_limits<long>::max()<<endl;
cout<<"unsigned long\t\t: "<<numeric_limits<unsigned long>::min()<<" to "<<numeric_limits<unsigned long>::max()<<endl;
cout<<"long long\t\t: "<<numeric_limits<long long>::min()<<" to "<<numeric_limits<long long>::max()<<endl;
cout<<"unsiged long long\t: "<<numeric_limits<unsigned long long>::min()<<" to "<<numeric_limits<unsigned long long>::max()<<endl;
cout<<"float\t\t\t: "<<numeric_limits<float>::min()<<" to "<<numeric_limits<float>::max()<<endl;
cout<<"double\t\t\t: "<<numeric_limits<double>::min()<<" to "<<numeric_limits<double>::max()<<endl;
cout<<"long double\t\t: "<<numeric_limits<long double>::min()<<" to "<<numeric_limits<long double>::max()<<endl;
}
The output will be:
Limits of Data types:
char : -128 to 127
unsigned char : 0 to 255
short : -32768 to 32767
unsigned short : 0 to 65535
int : -2147483648 to 2147483647
unsigned int : 0 to 4294967295
long : -2147483648 to 2147483647
unsigned long : 0 to 4294967295
long long : -9223372036854775808 to 9223372036854775807
unsigned long long : 0 to 18446744073709551615
float : 1.17549e-038 to 3.40282e+038
double : 2.22507e-308 to 1.79769e+308
long double : 3.3621e-4932 to 1.18973e+4932
For an unsigned data type, there isn't any sign bit and all bits are for data ; whereas for a signed data type, MSB is indicating a sign bit and the remaining bits are for data.
To find the range, do the following things:
Step 1: Find out number of bytes for the given data type.
Step 2: Apply the following calculations.
Let n = number of bits in data type
For signed data type ::
Lower Range = -(2^(n-1))
Upper Range = (2^(n-1)) - 1)
For unsigned data type ::
Lower Range = 0
Upper Range = (2^(n)) - 1
For example,
For unsigned int size = 4 bytes (32 bits) → Range [0, (2^(32)) - 1]
For signed int size = 4 bytes (32 bits) → Range [-(2^(32-1)), (2^(32-1)) - 1]
No, only part of ten digits number can be stored in a unsigned long int whose valid range is 0 to 4,294,967,295.
You can refer to this:
http://msdn.microsoft.com/en-us/library/s3f49ktz(VS.80).aspx
Can unsigned long int hold a ten digits number (1,000,000,000 - 9,999,999,999) on a 32-bit computer.
No
You should look at the specialisations of the numeric_limits<> template for a given type. It’s in the <limits> header.