Unsigned long long wrong given value after add - c++

I have two strings to add. Strings is HEX values. I convert strings to long long, add and after I back to string. But this operation no working good.
Code:
unsigned long long FirstNum = std::strtoull(FirstString.c_str(), NULL, 16);
unsigned long long SecondNum = std::strtoull(SecondString.c_str(), NULL, 16);
unsigned long long Num = FirstNum + SecondNum;
std::cout << " " << FirstNum << "\n+ " << SecondNum << "\n= " << Num << "\n\n";
I received
13285923899203179534
+ 8063907133566997305
= 2903086959060625223
Anyone can explain me this magic? How can I fix it?
Back to hex value by
std::stringstream Stream;
Stream << std::hex << Num;
return Stream.str();

All unsigned arithmetic in C (and C++) occurs modulo 2k for some k. In your case, you are getting the result modulo 264, implying that unsigned long long is 64 bits on your platform.
If you want to do arithmetic with integers larger than the largest supported type on your platform, you'll need to use a multiprecision library such as GMP

Related

Is there an alternative to char for storing one byte numeric values?

A char stores a numeric value from 0 to 255. But there seems to also be an implication that this type should be printed as a letter rather than a number by default.
This code produces 22:
int Bits = 0xE250;
signed int Test = ((Bits & 0x3F00) >> 8);
std::cout << "Test: " << Test <<std::endl; // 22
But I don't need Test to be 4 bytes long. One byte is enough. But if I do this:
int Bits = 0xE250;
signed char Test = ((Bits & 0x3F00) >> 8);
std::cout << "Test: " << Test <<std::endl; // "
I get " (a double quote symbol). Because char doesn't just make it an 8 bit variable, it also says, "this number represents a character".
Is there some way to specify a variable that is 8 bits long, like char, but also says, "this is meant as a number"?
I know I can cast or convert char, but I'd like to just use a number type to begin with. It there a better choice? Is it better to use short int even though it's twice the size needed?
cast your character variable to int before printing
signed char Test = ((Bits & 0x3F00) >> 8);
std::cout << "Test: " <<(int) Test <<std::endl;

How to convert an unsigned long long with leading zeroes to string?

I have a function that should take as parameter an unsigned long long in the hex format. I am trying to convert this parameter to a string to check if it is made of 16 digits or not, but I am having problems with leading zeros
template <typename T>
static string to_string(const T& value) {
stringstream oss;
oss << hex << setprecision(16) << value;
return oss.str();
}
int main(int argc, char** argv) {
unsigned long long pattern1 = 0x0000001000000002;
unsigned long long pattern2 = 0x0FFFFFFFFFFFFFFFF;
cout << "Pattern 1 = " << to_string(pattern1) << endl;
cout << "Pattern 2 = " << to_string(pattern2) << endl;
return 0;
}
What I want is for the pattern 1 to be converted with the zeroes to be able to check its length but this is the output. I tried using the set precision but didn't seem to help
Pattern 1 = 1000000002
Pattern 2 = ffffffffffffffff
Do you know how many characters should be in a number? The count of leading zeros can be infinite. I think this helps you
int character_count = 10;
oss << hex << setfill('0') << setw(character_count) << value;
You cannot know the number of the digits that was "entered by the user" except if you already read it through an "array" (char*, std::string, ...).
If you have an unsigned long long, the variable size will be 8 bytes anyway:
unsigned long long a = 0x1; // This will internally be: 0x0000000000000001
Now, if you want to get back the leading zeros from the actual type in the std::string, I think the following should do the trick (as already mentioned by other answers):
template <typename T>
std::string to_string(const T & val)
{
std::stringstream oss;
oss << std::hex << std::setfill('0') << std::setw(sizeof(T)*2) << val;
return oss.str();
}
But perhaps it could be better to overload the function for any integral types you want to use instead of using a template.
Because if someone calls the function with a type that is not a short, int, long, long long (resp. unsigned), the function will be broken.
The length of an unsigned long long represented as an hexadecimal number, including leading zeros, is:
sizeof(unsigned long long)*2
Since we are including leading zeros, the value of the unsigned long long is not relevant.

How to correctly truncate integral types

I've asked a similar question but after more research I came across something I cannot understand, and hopefully someone can explain what's causing this behavior:
// We wish to store a integral type, in this case 2 bytes long.
signed short Short = -390;
// In this case, signed short is required to be 2 bytes:
assert(sizeof(Short) == 2);
cout << "Short: " << Short << endl; // output: -390
signed long long Long = Short;
// in this case, signed long long is required to be 8 bytes long
assert(sizeof(Long) == 8);
cout << "Long: " << Long << endl; // output: -390
// enough bytes to store the signed short:
unsigned char Bytes[sizeof(Short)];
// Store Long in the byte array:
for (unsigned int i = 0; i < sizeof(Short); ++i)
Bytes[i] = (Long >> (i * 8)) & 0xff;
// Read the value from the byte array:
signed long long Long2 = (Bytes[0] << 0) + (Bytes[1] << 8);
cout << Long2 << endl; // output: 65146
signed short Short2 = static_cast<signed short>(Long2);
cout << Short2 << endl; // output: -390
output:
-390
-390
65146
-390
Can someone explain what's going on here? Is this undefined behavior? Why?
It is to do with the way negative numbers are stored. A negative number will begin with a 1 in its binary format.
signed long long Long = Short;
This is automatically doing a conversion for you. It isn't just assigning bits from one to the other, it is converting the value resulting in your 64-bit value starting with a 1 to indicate negative, and the rest denoting the 390 in 2s complement (can't be bothered working all the bits out).
signed long long Long2 = (Bytes[0] << 0) + (Bytes[1] << 8);
Now you're only retrieving the end two bytes, which will just represent the 390 magnitude. Your first two bytes will be zeros, so it thinks it is a positive number. It should work out as 2^16 - 390, and it does.
signed short Short2 = static_cast<signed short>(Long2);
This is an overflow. 65146 doesn't fit into a signed, 2-byte integer and so ends out populating the signing bit, making it get interpreted as negative. By no co-incidence, the negative number it represents is -390.

Printing long long integer accurately when using power function in C++

Can anyone explain how to print the accurate value?
int main() {
std::cout << pow(2,53);
}
//output=9.0072e+15
pow() takes double as parameters instead of integers. Luckily, this is precisely representable by unsigned long long, and 253 = (1 << 53).
Therefore, you could use
std::cout << (1ULL << 53);
If you want not to use bit shift (<<) you can forcibly use accurate type 'long long':
long long x = pow(2, 53);
cout << x;

Bit shifts in c++

I don't understand why this gives me the same answer:
long long a = 3265917058 >> 24;
std::cout << a << std::endl; //194
long long ip = 3265917058;
long long b = ip >> 24;
std::cout << b << std::endl; //194
but this don't:
long long a = (3265917058 << 16) >> 24;
std::cout << a << std::endl; //240
long long ip = 3265917058;
long long b = (ip << 16) >> 24;
std::cout << b << std::endl; //12757488 - **i want this to be 240 too!**
Update: I want 32bit shift , but how can i 32bit shift a number that is too large for an int variable?
Update2: My answer is to make unsigned int ip. Then everything will be ok.
Your literal constant 3265917058 is an int. Add a LL suffix to get the expected behavio(u)r:
long long a = (3265917058LL << 16) >> 24;
3265917058<<16 both sides are int, so the operation will be done in int (32-bits).
You need 3265917058LL<<16 then the left-side will be a long long and the operation will be done with that width i.e. 64-bits.
To get what you ask for:
long long ip=3265917058;
long long b= (static_cast<unsigned int>(ip)<<16)>> 24;
std::cout<<b<<std::endl; // 240
Note that the result you will get (240) is not portable. Mathematically, the result should be 12757488. The value 240 is due to truncation, and this is not guaranteed to happen. For instance, it doesn't happen on systems where int is 64 bits.