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.
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.
I have two numbers which are 32 digit decimal floating point numbers, like 1.2345678901234567890123456789012, I want to get the multiplication which is also 32 digit decimal floating point number. Is there any efficient way to do this?
Just use boost::multiprecision. You can use arbitrary precision but there is a typedef cpp_bin_float_50 which is a float with 50 decimal places.
Example for multiplying to big decimal numbers:
#include <iostream>
#include <boost/multiprecision/cpp_bin_float.hpp>
int main(){
boost::multiprecision::cpp_bin_float_50 val1("1.2345678901234567890123456789012");
boost::multiprecision::cpp_bin_float_50 val2("2.2345678901234567890123456789012");
std::cout << std::setprecision(std::numeric_limits< boost::multiprecision::cpp_bin_float_50>::max_digits10);
std::cout << val1*val2 << std::endl;
}
Output:
2.7587257654473404640618808351577828416864868162811293
Use the usual grade school algorithm (long multiplication). If you used 3 ints (instead of 4):
A2A1A0 * B2B1B0 = A2*B2 A2*B1 A2*B0
A1*B2 A1*B1 A1*B0
A0*B2 A0*B1 A0*B0
Every multiplication will have a 2-int result. You have to sum every column on the right side, and propagate carry. In the end, you'll have a 6-int result (if inputs are 4-int, then the result is 8-int). You can then round this 8-int result. This is how you can handle the mantissa part. The exponents should just be added together.
I recommend you to divide a problem into two parts:
multiplying a long number with an int
adding the result from 1. into the final result
You'll need something like this as a workhorse (note that this code assumes that int is 32-bit, long long is 64-bit):
void wideMul(unsigned int &hi, unsigned int &lo, unsigned int a, unsigned int b) {
unsigned long long int r = (unsigned long long int)a*b;
lo = (unsigned int)r;
hi = (unsigned int)(r>>32);
}
Note: that if you had larger numbers, there are faster algorithms.
I need to do the following calculation in a c++ code:
(((n*log(n)) / log(4)) + 1)
Where n is of type 'unsigned long long int' (and is a power of 2, so result should be integer).
For very large numbers i get some errors e.g for n = 9007199254740992 result should be 238690780250636289, but when i run the code i get 238690780250636288.
Could this be the result of 'log' function not having an implementation with 'unsigned long long int' argument? If so is there a way to circumvent it this without implementing a new log function?
unsigned long long int upToBit(unsigned long long int n) {
unsigned long long int check = (((n*log(n)) / log(4)) + 1);
return check;
}
Could this be the result of 'log' function not having an implementation with 'unsigned long long int' argument?
Yes and no.
You use std::log which returns double. double cannot represent 238690780250636289 because of the extended range. If you simply convert that number to long long, you'll get exactly the same error:
int main()
{
volatile double dd = 238690780250636289.0;
printf("%lld\n", (long long)dd);
}
Output:
238690780250636288
To understand why that happens, there is a good paper about floating point numbers.
You may have luck with long double version of log if sizeof(long double) is > 8 on your compiler. You may also test "correctness" of your computation:
bool resultOk = upToBit(9007199254740992) == 238690780250636289.0;
In general, double has 52-bit mantissa and because of extra hidden bit maximum reliable integer that double can represent is 2 power 53 or 9007199254740992. If your resulting double has higher integer value then simple integer math sometimes "stops working":
#include <stdio.h>
int main()
{
long long l = 9007199254740992;
double d = (double)l;
d += 1;
printf("9007199254740992 + 1 = %lld\n", (long long)d);
}
Output:
9007199254740992 + 1 = 9007199254740992
To get better precision you can use some of the multiple precision arithmetic libraries that are designed to do that. GCC for example uses GMP / MPFR for its internal calculations.
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)