C++ safeguards exceeding limits of integer - c++

I am working on a chapter review of a book: at the end of the chapter there are some questions/tasks which you are to complete.
I decided to do them in the format of a program rather than a text file:
#include <iostream>
int main(int argc, char* argv[]) {
std::cout << "Chapter review\n"
<< "1. Why does C++ have more than one integer type?\n"
<< "\tTo be able to represent more accurate values & save memory by only allocating what is needed for the task at hand.\n"
<< "2. Declare variables matching the following descriptions:\n"
<< "a.\tA short integer with the value 80:\n";
short myVal1 = 80;
std::cout << "\t\t\"short myVal1 = 80;\": " << myVal1 << std::endl
<< "b.\tAn unsigned int integer with the value 42,110:\n";
unsigned int myVal2 = 42110;
std::cout << "\t\t\"unsigned int myVal2 = 42110;\": " << myVal2 << std::endl
<< "c.\tAn integer with the value 3,000,000,000:\n";
float myVal3 = 3E+9;
std::cout << "\t\t\"float myVal3 = 3E+9;\": " << static_cast<unsigned int>(myVal3) << std::endl
<< "3. What safeguards does C++ provide to keep you from exceeding the limits of an integer type?\n"
<< "\tWhen it reaches maximum number it starts from the begging again (lowest point).\n"
<< "4. What is the distinction between 33L and 33?\n"
<< "\t33L is of type long, 33 is of type int.\n"
<< "5. Consider the two C++ statements that follow:\n\tchar grade = 65;\n\tchar grade = 'A';\nAre they equivalent?\n"
<< "\tYes, the ASCII decimal number for 'A' is '65'.\n"
<< "6. How could you use C++ to find out which character the code 88 represents?\nCome up with at least two ways.\n"
<< "\t1: \"static_cast<char>(88);\": " << static_cast<char>(88) << std::endl; // 1.
char myChar = 88;
std::cout << "\t2: \"char myChar = 88;\": " << myChar << std::endl // 2.
<< "\t3: \"std::cout << (char) 88;\" " << (char) 88 << std::endl // 3.
<< "\t4: \"std::cout << char (88);\": " << char (88) << std::endl // 4.
<< "7. Assigning a long value to a float can result in a rounding error. What about assigning long to double? long long to double?\n"
<< "\tlong -> double: Rounding error.\n\tlong long -> double: Significantly incorrect number and/or rounding error.\n"
<< "8. Evaluate the following expressions as C++ would:\n"
<< "a.\t8 * 9 + 2\n"
<< "\t\tMultiplication (8 * 9 = 72) -> addition (72 + 2 = 74).\n"
<< "b.\t6 * 3 / 4\n"
<< "\t\tMultiplication (6 * 3 = 18 -> division (18 / 4 = 4).\n"
<< "c.\t3 / 4 * 6\n"
<< "\t\tDivision (3 / 4 = 0) -> multiplication (0 * 6 = 0).\n"
<< "d.\t6.0 * 3 / 4\n"
<< "\t\tMultiplication (6.0 * 3 -> 18.0) -> division (18.0 / 4 = 4.5).\n"
<< "e.\t 15 % 4\n"
<< "\t\tDivision (15 / 4 = 3.75) Then returns the reminder, basically how many times can 4 go into 15 in this case that is 3 (3*4 = 12).\n"
<< "9. Suppose x1 and x2 are two type of double variables that you want to add as integers and assign to an integer variable. Construct a C++ statement for doing so. What if you wanted to add them as type double and then convert to int?\n"
<< "\t1: \"int myInt = static_cast<double>(doubleVar);\"\n\t2: \"int myInt = int (doubleVar);\".\n"
<< "10. What is the variable type for each of the following declarations?\n"
<< "a.\t\"auto cars = 15;\"\n\t\tint\n"
<< "b.\t\"auto iou = 150.37f;\"\n\t\tfloat\n"
<< "c.\t\"auto level = 'B';\"\n\t\tchar\n"
<< "d.\t\"auto crat = U'/U00002155';\"\n\t\twchar_t ?\n"
<< "e.\t\"auto fract = 8.25f/.25;\"\n\t\tfloat" << std::endl;
return 0;
}
It's been a while since I read chapter 3 due to moving/some other real life stuff.
What I am unsure about here is basically question number 3: it says safeguards as in plural.
However I am only aware of one: that it starts from the beginning again after reaching maximum value? Am I missing something here?
Let me know if you see any other errors also - I am doing this to learn after all :).

Basically I can't accept a comment as an answer so to sum it up:
There are none safeguards, I misunderstood that question which #n.m. clarified for me.
10.e was wrong as pointed out by #Jarod42, which is correct.
Thanks!

As for me "Declare variable of integer with the value 3,000,000,000" is:
unsigned anInteger = 3000000000;
cause c++ the 11th supplies 15 integer types and unsigned int is the smallest that can store such a big integer as 3 000 000 000.

C++ classifies integer overflow as "Undefined Behavior" - anything can happen as a result of it. This by itself may be called a "safeguard" (though it's a stretch), by the following thinking:
gcc has that -ftrapv compilation switch that makes your program crash when integer overflow happens. This allows you to debug your overflows easily. This feature is possible because C++ made it legal (by nature of Undefined Behavior) to make your program crash in these circumstances. I think the C++ Committee had this exact scenario in mind when making that part of the C++ Standard.
This is different from e.g. Java, where integer overflow causes wraparound, and is probably harder to debug.

Related

Integer Arithmetics Going Wild

Please, could somebody explain what's happening under the hood there?
The example runs on an Intel machine. Would the behavior be the same on other architectures?
Actually, I have a hardware counter which overruns every now and then, and I have to make sure that the intervals are always computed correctly. I thought that integer arithmetics should always do the trick but when there is a sign change, binary subtraction yields an overflow bit which appears to be actually interpreted as the sign.
Do I really have to handle the sign by myself or is there a more elegant way to compute the interval regardless of the hardware or the implementation?
TIA
std::cout << "\nTest integer arithmetics\n";
int8_t iFirst = -2;
int8_t iSecond = 2;
int8_t iResult = iSecond - iFirst;
std::cout << "\n" << std::to_string(iSecond) << " - " << std::to_string(iFirst) << " = " << std::to_string(iResult);
iResult = iFirst - iSecond;
std::cout << "\n" << std::to_string(iFirst) << " - " << std::to_string(iSecond) << " = " << std::to_string(iResult);
iFirst = SCHAR_MIN + 1; iSecond = SCHAR_MAX - 2;
iResult = iSecond - iFirst;
std::cout << "\n" << std::to_string(iSecond) << " - " << std::to_string(iFirst) << " = " << std::to_string(iResult);
iResult = iFirst - iSecond;
std::cout << "\n" << std::to_string(iFirst) << " - " << std::to_string(iSecond) << " = " << std::to_string(iResult) << "\n\n";
And this is what I get:
Test integer arithmetics
2 - -2 = 4
-2 - 2 = -4
125 - -127 = -4
-127 - 125 = 4
What happens with iResult = iFirst - iSecond is that first both variables iFirst and iSecond are promoted to int due to usual arithmetic conversion. The result is an int. That int result is truncated to int8_t for the assignment (in effect, the top 24 bits of the 32-bit int is cut away).
The int result of -127 - 125 is -252. With two's complement representation that will be 0xFFFFFF04. Truncation only leaves the 0x04 part. Therefore iResult will be equal to 4.
the problem is that your variable is 8 bit. 8 bits can hold up to 256 numbers. So, your variables can only represent numbers within -128~127 range. Any number out of that range will give wrong output. Both of your last calculations produce numbers beyond the variable's range (252 and -252). There is no elegant or even possible way to handle it as it is. You can only handle the overflow bit yourself.
PS. This is not hardware problem. Any processor would give same results.

Returning incorrect values of floor function in C++ [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 2 years ago.
The code:
cout << log(25.0/9.0)/log(5.0/3.0) << endl << floor(log(25.0/9.0)/log(5.0/3.0));
results:
2
1
Why does C++ considers floor(2) = 1?
What I tried:
When saving the fraction in a float it returns the correct value:
float a = log(25.0/9.0)/log(5.0/3.0);
cout << a << endl << floor(a);
results:
2
2
Set your precision. floor is correct;
std::cout << std::fixed << std::setprecision(20) << std::endl << log(25.0 / 9.0) / log(5.0 / 3.0) << std::endl << floor(log(25.0 / 9.0) / log(5.0 / 3.0)) << std::endl;
float a = log(25.0 / 9.0) / log(5.0 / 3.0);
std::cout << std::fixed << std::setprecision(20) << std::endl<< a << std::endl << floor(a) << std::endl;
double b = log(25.0 / 9.0) / log(5.0 / 3.0);
std::cout << std::fixed << std::setprecision(20) << std::endl << b << std::endl << floor(b) << std::endl;
this produces
1.99999999999999955591
1.00000000000000000000
2.00000000000000000000
2.00000000000000000000
1.99999999999999955591
1.00000000000000000000
I complied and checked the whole code and let me share my analysis with you.
If you do log(25.0/9.0)/log(5.0/3.0) division directly the compiler treats it as double and the double division result is equal to 1.9999999999999996. If it is rounded it will become 2 and if floor operation is done on this it will become 1 as floor() function in C++ returns the largest possible integer value which is less than or equal to the given argument. In this example it will always return 1.
If the division log(25.0/9.0)/log(5.0/3.0) is treated as float it will result in 2.0000000039152304 (treating each operand as float and storing result in double for understanding) hence in this case round and floor operation will have same result that is 2.
Good Luck
I had same problem two days ago when I was solving a problem on Codeforces. I was using floor function and its returning its different value. I went to google and found some answers here on stackoverflow telling me to use cout << std::fixed, but this function will return float values with decimal point which is not accepted on Codeforces. After a little bit of google search I found this following formula to calculate floor value of a/b.
floor = (a/b) + ((a%b)!=0)
Hope this helps :)

Strange static cast behaviour in a member function of class used as template parameter

Within a member function of a class used as a template paramter, I have a function containing the following code:
double x = /*Something operation returning double*/;
x /= CubeWidth; /*CubeWidth is a class member*/
cout << "Element after centering and normalization = " << x << endl;
cout << "and after adding 1 and truncating = " << x+1 << endl;
cout << "then static cast = " << (int) x+1 << endl;
The output of this function is
Element after centering and normalization = 1
and after adding 1 and truncating = 2
then static cast = 1
Obviously, the last line should give an answer 2.
If I instantiate exactly the same class without using it as the template parameter, I don't get this printout, rather I have the correct one.
Can anyone tell me why this is happening?
Most likely x (a double) is not exactly 1, it is 0.9999999.... Check its exact value by printing x==1.0 or x<1.0 and see what is really true. Or add more digits to the output:
cout << "and after adding 1 and truncating = " << setprecision( 15 ) << x+1 << endl;
The rounding to integer will throw away all digits after the comma, so 1.999999... becomes 1.

Unexpected Mathematical Division Output - C++

I have this segment of testing code (there is quite a lot of other material; however, it is extremely dense and likely irrelevant to this question), which has been producing some inexplicable output. When compiled, this block:
cout << team1[m].rating << endl;
cout << team2[n].rating << endl;
cout << team1.size() << endl;
cout << team2.size() << endl;
cout << (team2[n].rating - team1[m].rating) / team2.size() << endl;
cout << (team1[m].rating - team2[n].rating) / team1.size() << endl;
produces the output:
10
30
2
2
10
2147483638
'team1' and 'team2' are both of type vector<player> (without backslash) and the 'player' struct appears as follows:
struct player {
string name;
int rating;
player(string Name, int Rating) :
name(Name), rating(Rating) {}
};
team1.size() and team2.size() are unsigned (size_t) - change your code to:
cout << (team2[n].rating - team1[m].rating) / static_cast<int>(team2.size()) << endl;
cout << (team1[m].rating - team2[n].rating) / static_cast<int>(team1.size()) << endl;
(team1[m].rating - team2[n].rating) is equal to -20. This expression result is being promoted to unsigned int according to rules of mixed expressions and divided by team1.size(), yielding 2147483638 which is the unsigned int equivalent for signed int -10.
This occurs because the size() function of std::vector returns a size_t, which is unsigned. When dividing an int (such as the rating) by a size_t, the int is promoted to an unsigned int.
Converting a negative number to an unsigned value will cause that value to underflow, becoming larger than the maximum positive value which can be represented by the original signed type.
In order to prevent this, you need to explicitly state that the size() arguments should be converted to int before the division.
cout << (team2[n].rating - team1[m].rating) / static_cast<int>(team2.size()) << endl;
cout << (team1[m].rating - team2[n].rating) / static_cast<int>(team1.size()) << endl;

Kinds of integer overflow on subtraction

I'm making an attempt to learn C++ over again, using Sams Teach Yourself C++ in 21 Days (6th ed.). I'm trying to work through it very thoroughly, making sure I understand each chapter (although I'm acquainted with C-syntax languages already).
Near the start of chapter 5 (Listing 5.2), a point is made about unsigned integer overflow. Based on their example I wrote this:
#include <iostream>
int main () {
unsigned int bignum = 100;
unsigned int smallnum = 50;
unsigned int udiff;
int diff;
udiff = bignum - smallnum;
std::cout << "Difference (1) is " << udiff << "\n";
udiff = smallnum - bignum;
std::cout << "Difference (2) is " << udiff << "\n";
diff = bignum - smallnum;
std::cout << "Difference (3) is " << diff << "\n";
diff = smallnum - bignum;
std::cout << "Difference (4) is " << diff << "\n";
return 0;
}
This gives the following output, which is not surprising to me:
Difference (1) is 50
Difference (2) is 4294967246
Difference (3) is 50
Difference (4) is -50
If I change the program so that the line declaring bignum reads instead unsigned int bignum = 3000000000; then the output is instead
Difference (1) is 2999999950
Difference (2) is 1294967346
Difference (3) is -1294967346
Difference (4) is 1294967346
The first of these is obviously fine. The number 1294967346 is explained by the fact that 1294967346 is precisely 2^32 - 3000000000. I don't understand why the second line doesn't read 1294967396, owing to the 50 contributed by smallnum.
The third and fourth lines I can't explain. How do these results come about?
Edit: For the third line - does it give this result just by finding the solution modulo 2^32 that fits in the range of values allowed for a signed int?
2^32 - 3000000000 = 1294967296 (!)