C++: convert unsigned long long to unsigned long - c++

I am trying to convert an unsigned long long to unsigned long. Is the following a correct way to do it?
unsigned long removeExtraBits2(unsigned long long c) {
return (unsigned long) ((c << 32) >> 32);
}
If not, can you provide a working example?
My assumption is that when shifting left, and then back right, the 32 leftmost bits get set to 0.
Thanks!
EDIT: The purpose of the conversion is to get rid of the extra bits, 'higher' than the 32nd, effectively keeping only the rightmost 32 bits into an unsigned long.

Just do a "plain" cast ((unsigned long)c, or, if you like verbosity, static_cast<unsigned long>(c), or even just assign the unsigned long long source value to the unsigned long target variable), the standard guarantees that the extra bits on the left will get truncated.
If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type).
(C++11, §4.7 ¶2)
which, if the source is unsigned (or is signed and in 2's complement arithmetic), is a fancy way to say that the extra bits are truncated.

There are many different processors and operating systems. The unsigned long long is 64-bits almost on everything. The unsigned long is the other story. It is for example 64-bits on Linux x86-64, 32-bits on Linux x86-32 and 32-bits on Windows x86-64 and x86-32. Plain convert may be noop.
I think this is a safe solution.
unsigned long removeExtraBits(unsigned long long c) {
c %= 0x100000000ULL;
return (unsigned long)(c);
}
Compiler will change % to simple mov.

Related

Why doesn't this snippet of code print the number normally?

Why do I get two different results? Unsigned long is big enough to handle such number, and it can't be an overflow of some kind, right?
I am deliberately trying to make it show in decimal form, but it just doesn't work.
What could be the reason?
#include <iostream>
using namespace std;
void Print(unsigned long num)
{
cout<<dec<<num<<endl;
}
int main()
{
Print(9110865112);
cout<<dec<<9110865112;
return 0;
}
Edit
It outputs:
520930520
9110865112
unsigned long is not always sufficiently large. With 32 bits it can occupy integers from 0 up to and including 232-1, which is about four billions. 9'110'865'112 is nine billions and would thus not fit into unsigned long.
Try outputting sizeof unsigned long and see what you get.
Also, consider your output: 9110865112 mod 232 is 520930520, which basically proves that unsigned long is 32 bit large on your machine.
The problem is that the numeric literal that you specify is too large to fit in an unsigned long.
When you use the literal directly, the compiler treats it as long long, and chooses the proper overload for operator <<.
To fix this problem, use unsigned long long in the signature of the Print function:
void Print(unsigned long long num)
{
cout<<dec<<num<<endl;
}
Demo.
Because 9,110,865,112 is greater than 32 bits, the method is only accepting 32 of the bits even though you're trying to pass it more.
To fix this, you should use an unsigned long long data type for you num parameter. When you print it directly written as a constant, the code prints out find because the compiler says that constant is an unsigned long long, but when you pass it as an unsigned long, the compiler says that constant should be an unsigned long. Because it's not an unsigned long, it drops some of the bits. (I'm suprised your compiler didn't print out a warning.)
As a reference, an unsigned long can hold values between 0 and 4,294,967,295 (inclusive). Any value great than this should be assigned a larger data type. An unsigned long long can hold values between 0 and 18,446,744,073,709,551,615 (inclusive).
It is worth noting that frequently the data types uint32_t and uint64_t are used in place of unsigned long and unsigned long long respectively. The u denotes that the number is unsigned (if the u is left out, the number is assumed to be signed). The number (64 and 32 in this case) states how many bytes the number should have. And _t at the end just indicates that this is a data type. So (u)int#_t is a common way to write numeric data types; # can be 8, 16, 32, or 64 in standard C++ depending on the number of bits you need.
To summarize: You're throwing a number that's too large at the function. You need to change your function's parameters to support this number:
void Print(uint64_t num){
cout << dec << num << endl;
}

convert from long long to int and the other way back in c++

How to convert from long long to int and the other way back in c++ ??
also what are the properties of long long , especially its maximum size,
thank in advance ..
int is guaranteed to be at least 16 bits wide. On modern systems, it's most commonly 32 bits (even on 64-bit systems).
long long, which didn't originally exist in C++, is guaranteed to be at least 64 bits wide. It's almost always exactly 64 bits wide.
The usual way to convert a value from one integer type to another is simply to assign it. Any necessary conversion will be done implicitly. For example:
int x = 42;
long long y = 9223372036854775807;
y = x; // implicitly converts from int to long long
x = y; // implicitly converts from long long to int
For a narrowing conversion, where the target type can't represent all the values of the source type, there's a risk of overflow; int may or may not be able to hold the value 9223372036854775807. In this case, the result is implementation-defined. The most likely behavior is that the high-order bits are discarded; for example, converting 9223372036854775807 to int might yield 2147483647. (This is clearer in hexadecimal; the values are 0x7fffffffffffffff and 0x7fffffff, respectively.)
If you need to convert explicitly, you can use a cast. A C-style cast uses the type name in parentheses:
(long long)x
Or you can use a C++-style static_cast:
static_cast<long long>(x)
which is somewhat safer than a C-style cast because it's restricted in which types it can operate on.
Type long long is typically 64 bits.
Type int is likely to be 32 bits, but not on all machines.
If you cast an int to a long long, you can do
my_long_long = (long long) my_int
and it will be just fine. If you go the other direction, like
my_int = (int) my_long_long
and the int is smaller than 64-bits, it won't be able to hold all the information, so the result may not be correct.
Size of int is only 2 bytes whereas the other one is usually larger than int. So if you are looking to convert long into int then you would end up loosing information. But the other way is possible without sacrificing the correctness of information.
Suppose a is of long type and b is of int type. Then int to long covertion:a=(long)b; . For other way:b=(int)a;.

What is the difference between long long and long int

I know the difference between long and int
But What is the difference between "long long" and "long int"
There are several shorthands for built-in types.
short is (signed) short int
long is (signed) long int
long long is (signed) long long int.
On many systems, short is 16-bit, long is 32-bit and long long is 64-bit. However, keep in mind that the standard only requires
sizeof(char) == 1
sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
And a consequence of this is that on an exotic system, sizeof(long long) == 1 is possible.
According to the C standard the integral types are defined to provide at least the following ranges:
int -32767 to +32767 representable in 16 bits
long -2147483647 to +2147483647 representable in 32 bits
long long -9223372036854775807 to +9223372036854775807 representable in 64 bits
Each can be represented as to support a wider range. On common 32 bit systems int and long have the same 32 bit representation.
Note that negative bounds are symmetric to their positive counterparts to allow for sign and magnitude representations: the C language standard does not impose two's complement.
long long may be a bigger type than long int. For example on x86 32 bit long long would be a 64-bit type rather than 32 bit for long int.
On 64 bit systems it doesn't make any difference in their sizes. On 32 bit systems long long is guaranteed store values of 64 bit range.
Just to avoid all these confusions, it is always better to use the standard integral types: (u)int16_t, (u)int32_t and (u)int64_t available via stdint.h which provides transparency.
An int on 16 bit systems was 16 bits. A "long" was introduced as a 32 bit integer, but on 32 bit systems long and int mean the same thing (both are 32 bit.) So on 32 and 64 bit systems, long long and long int are both 64 bit. The exception is 64 bit UNIX where long is 64 bits.
See the integer Wikipedia article for a more detailed table.
long int is a synonym for long. long long int is a synonym for long long.
The only guarantee you have in standard C++ is that long long is at least as large as long but can be longer. This is specified in §3.9.1.2 in the most recent publicly available draft of the standard n3242.
The C standard doesn't make any specific width requirements for integral types other than minimal ranges of values that the type needs to be able to represent, and that the widths are non-decreasing: short <= int <= long int <= long long int (similarly for the unsigned types). long long only became part of the standard in C99 and C++0x, by the way. The minimum required ranges can be found in this Wikipedia article.
I think:
"long" doubles the number of bits allocated to the data type.
So long (32 bits?) becomes 64 bits.
Int (16 bits?) becomes 32 bits.

The difference between unsigned long and UINT64

What is the difference between unsigned long and UINT64?
I think they are the same, but I'm not sure.
The definition of UINT64 is :
typedef unsigned __int64 UINT64
(by using StdAfx.h)
UINT64 is specific and declares your intent. You want a type that is an unsigned integer that is exactly 64 bits wide. That this may be equal to an unsigned long on some platforms is coincidence.
The C++ standard does not define the sizes of each of the types (besides char), so the size of unsigned long is implementation defined. In most cases I know of, though, unsigned long is an unsigned 32 bit type, while UINT64 (which is an implementation type, not even mentioned in the standard) is a 64 bit unsigned integer in VS.
The unsigned long type size could change depending on the architecture of the system you are on, while the assumption is that UINT64 is definitely 64 bits wide. Have a look at http://en.wikipedia.org/wiki/C_variable_types_and_declarations#Size
See http://msdn.microsoft.com/en-us/library/s3f49ktz(VS.90).aspx
You want to see the difference between unsigned long and unsigned __int64.
A long is typically 32 bits (but this may very per architecture) and an uint64 is always 64 bits. A native data type which is sometimes 64 bits long is a long long int.

C++ long overflowing prematurely

I'm having a bizarre problem with C++ where the long data type is overflowing long before it should. What I'm doing (with success so far) is to have integers behave like floats, so that the range [-32767,32767] is mapped to [-1.0,1.0]. Where it stumbles is with larger arguments representing floats greater than 1.0:
inline long times(long a, long b) {
printf("a=%ld b=%ld ",a,b);
a *= b;
printf("a*b=%ld ",a);
a /= 32767l;
printf("a*b/32767=%ld\n",a);
return a;
}
int main(void) {
printf("%ld\n",times(98301l,32767l));
}
What I get as output is:
a=98301 b=32767 a*b=-1073938429 a*b/32767=-32775
-32775
So times(98301,32767) is analogous to 3.0*1.0. This code works perfectly when the arguments to times are less than 32767 (1.0), but none of the intermediate steps with the arguments above should overflow the 64 bits of long.
Any ideas?
long is not necessarily 64 bits. try 'long long' instead.
The type long is not necessarily 64 bits. If you are on the 32 bit architecture (at least on MS Visual c++), the long type is 32 bits. Check it out with sizeof (long). There is also the long long data type that may help.
You probably have 32-bit longs. Try using long long instead.
98301 * 32767 = 3221028867, while a 32-bit long overflows at 2147483648
The C standard only guarantees that long will have at least 32 bit (which is actually the case on most 32bit platforms).
If you need 64 bit, use long long. It's guaranteed to hold at least 64 bit.