Solving Equality Equation in c++ - c++

I want to calculate maximum value(int) of i for which (i*(i+1)(2i+1))/3 < 4,294,967,295 (int limit).
int main()
{
unsigned int i=1;
unsigned int l=std::numeric_limits<unsigned int>::max();
while(l>((i*(i+1)*(2*i+1))/3))
{
i++;
}
cout<<(i-1);getchar();return 0;
}

Your problem is caused comparing unsigned int l to an expression casted to int, this gives undefined results. In the second case the inner expression is all evaluated to an unsigned int and casted to int after evaluation (with a loss of precision that might cut the positive value). In your first case the nominator of the division function is casted to int before the division applies.
You should better write your condition like this, or even better omit the cast at all (there's no single float or double math operation done in your expression, you're dealing solely with unsigned int):
while(l>(unsigned int)(i*(i+1)*(2*i+1))/3) { // ...
// ^^^^^^^^
If you do so, you'll always experience your loop running endlessly or very long. IMHO it makes no sense, to check if the result of the condition expression might be bigger than std::numeric_limits<unsigned int>::max(), it cannot be bigger.

This code will not give you the correct answer. The calculation can be rewritten as (i*(i+1)*(2*i+1)) < 3 * 4,294,967,295, now consider what that means about the calculation of the left hand side.

The inequality appearing in while loop is of order 3. this type of curve has very high slope,meaning small change in co-ordinate produces huge amount in y. while loop soon encounter in comparison of unsigned int and overflow of i, thus gives never ending loop(Yes never ending, i tried).
The solution is simple. break the in-equality in logarithm. Now the 3rd order polynomial is linear of log. Eventually it worked.

Related

why do I get different results with the same conditions in a for loop?

I was stuck when I was trying to use a for loop to solve a problem.
Here's my simplified code:
int main(int argc, const char * argv[])
{
std::vector<int> a;
a.push_back(2333);
int n = 10, m = 10;
for(int i=0; i< -1; i++)
m--;
std::cout<<m<<endl;
for(int j=0; j<a.size()-2; j++)
n--;
std::cout<<n<<endl;
return 0;
}
Apparently, a.size() = 1 so these two end conditions should be the same. However, when I ran my code on Xcode 9.4.1 I got unexpected as it turned out that m = 10
and n = 11. And I found that the time it took to get the value of n is much longer than m.
Why would I get such a result? Any help will be appreciated.
The value returned by size() is std::size_t, which is an unsigned integral type. This means that it can only represent non-negative numbers, and if you do an operation that results in a negative number, it will wrap around to the largest possible value like in modular arithmetic.
Here, 2 - 1 is -1, which wraps to 2^32 - 1 on a 32-bit system. When you try to subtract 2^32 - 1 from 10, you cause a signed integer underflow since the minimum value of a 32-bit integer is -2^31. Signed integer overflow/underflow is undefined behavior, so anything can happen.
In this case, it seems like the underflow wrapped around to the maximum value. So the result would be 10 - (2^32 - 1) + 2^32, which is 11. We add 2^32 to simulate the underflow wrapping around. In other words, after the 2^31 + 10th iteration of the loop, n is the minimum possible value in a 32-bit integer. The next iteration causes the wrap around, so n is now 2^31 - 1. Then, the remaining 2^31 - 12 iterations decrease n to 11.
Again, signed integer overflow/underflow is undefined behavior, so don't be surprised when something weird happens because of that, especially with modern compiler optimizations. For example, your entire program can be "optimized" to do absolutely nothing since it will always invoke UB. You're not even guaranteed to see the output from std::cout<<m<<endl;, even though the UB is invoked after that line executes.
The value returned by a.size() is it type size_t, which is an unsigned int, because there wouldn’t be any reason to have a size that is negative. If you do 1-2 with unsigned numbers it will roll over and become a value near the maximum value for an unsigned int and the loop will take quite a while to run, or might not even stop since a signed integer can’t be larger than the top half of unsigned values. This depends on the rules of comparing signed and unsigned which I don’t remember for sure on the spot.
Using a debugger and making sure the types are correct (your compiler should mention signed/unsigned mismatch here) helps determine these cases.

C++ string.length() Strange Behavior

I just came across an extremely strange problem. The function I have is simply:
int strStr(string haystack, string needle) {
for(int i=0; i<=(haystack.length()-needle.length()); i++){
cout<<"i "<<i<<endl;
}
return 0;
}
Then if I call strStr("", "a"), although haystack.length()-needle.length()=-1, this will not return 0, you can try it yourself...
This is because .length() (and .size()) return size_t, which is an unsigned int. You think you get a negative number, when in fact it underflows back to the maximum value for size_t (On my machine, this is 18446744073709551615). This means your for loop will loop through all the possible values of size_t, instead of just exiting immediately like you expect.
To get the result you want, you can explicitly convert the sizes to ints, rather than unsigned ints (See aslgs answer), although this may fail for strings with sufficient length (Enough to over/under flow a standard int)
Edit:
Two solutions from the comments below:
(Nir Friedman) Instead of using int as in aslg's answer, include the header and use an int64_t, which will avoid the problem mentioned above.
(rici) Turn your for loop into for(int i = 0;needle.length() + i <= haystack.length();i ++){, which avoid the problem all together by rearranging the equation to avoid the subtraction all together.
(haystack.length()-needle.length())
length returns a size_t, in other words an unsigned int. Given the size of your strings, 0 and 1 respectively, when you calculate the difference it underflows and becomes the maximum possible value for an unsigned int. (Which is approximately 4.2 billions for a storage of 4 bytes, but could be a different value)
i<=(haystack.length()-needle.length())
The indexer i is converted by the compiler into an unsigned int to match the type. So you're gonna have to wait until i is greater than the max possible value for an unsigned int. It's not going to stop.
Solution:
You have to convert the result of each method to int, like so,
i <= ( (int)haystack.length() - (int)needle.length() )

Acting like unsigned int overflow. What is causing it?

I have this function which generates a specified number of so called 'triangle numbers'. If I print out the deque afterwords, the numbers increase, jumps down, then increases again. Triangle numbers should never get lower as i rises so there must be some kind of overflow happening. I tried to fix it by adding the line if(toPush > INT_MAX) return i - 1; to try to stop the function from generating more numbers (and return the number it generated) if the result is overflowing. That is not working however, the output continues to be incorrect (increases for a while, jumps down to a lower number, then increases again). The line I added doesn't actually seem to be doing anything at all. Return is not being reached. Does anyone know what's going on here?
#include <iostream>
#include <deque>
#include <climits>
int generateTriangleNumbers(std::deque<unsigned int> &triangleNumbers, unsigned int generateCount) {
for(unsigned int i = 1; i <= generateCount; i++) {
unsigned int toPush = (i * (i + 1)) / 2;
if(toPush > INT_MAX) return i - 1;
triangleNumbers.push_back(toPush);
}
return generateCount;
}
INT_MAX is the maximum value of signed int. It's about half the maximum value of unsigned int (UINT_MAX). Your calculation of toPush may well get much higher than UINT_MAX because you square the value (if it's near INT_MAX the result will be much larger than UINT_MAX that your toPush can hold). In this case the toPush wraps around and results in smaller value than previous one.
First of all, your comparison to INT_MAX is flawed since your type is unsigned int, not signed int. Secondly, even a comparison to UINT_MAX would be incorrect since it implies that toPush (the left operand of the comparison expression) can hold a value above it's maximum - and that's not possible. The correct way would be to compare your generated number with the previous one. If it's lower, you know you have got an overflow and you should stop.
Additionally, you may want to use types that can hold a larger range of values (such as unsigned long long).
The 92682th triangle number is already greater than UINT32_MAX. But the culprit here is much earlier, in the computation of i * (i + 1). There, the calculation overflows for the 65536th triangular number. If we ask Python with its native bignum support:
>>> 2**16 * (2**16+1) > 0xffffffff
True
Oops. Then if you inspect your stored numbers, you will see your sequence dropping back to low values. To attempt to emulate what the Standard says about the behaviour of this case, in Python:
>>> (int(2**16 * (2**16+1)) % 0xffffffff) >> 1
32768
and that is the value you will see for the 65536th triangular number, which is incorrect.
One way to detect overflow here is ensure that the sequence of numbers you generate is monotonic; that is, if the Nth triangle number generated is strictly greater than the (N-1)th triangle number.
To avoid overflow, you can use 64-bit variables to both generate & store them, or use a big number library if you need a large amount of triangle numbers.
In Visual C++ int (and of course unsigned int) is 32 bits even on 64-bit computers.
Either use unsigned long long or uint64_t to use a 64-bit value.

Finding the Sum of 2D vector

Having some trouble finding the sum of a 2D vector. Does this look ok?
int sumOfElements(vector<iniMatrix> &theBlocks)
{
int theSum = 0;
for(unsigned i=0; (i < theBlocks.size()); i++)
{
for(unsigned j=0; (j < theBlocks[i].size()); j++)
{
theSum +=theBlocks[i][j];
}
}
return theSum;
}
It returns a negative number, however, it should return a positive number..
Hope someone can help :)
The code looks proper in an abstract sense, but you may be overflowing theSum. You can try making theSum type double to see what value you get to help sort out the proper integral type to use for it.
double sumOfElements(vector<iniMatrix> &theBlocks)
{
double theSum = 0;
/* ... */
return theSum;
}
When you observe the returned value, you can see if it would fit in an int or if you need to use a wider long or long long type.
If all the values in the matrix are positive, you should consider using one of the unsigned integral types. which would double your range of allowed values.
The problem is obviously the int exceeds its boundary (like others said)
For signed data types it becomes negative when overflow, and for unsigned datatypes it starts from zero again after overflow.
If you want to detect overflow pragmatically, you can paste these lines instead of the additional line.
if( theSum > int(theSum + theBlocks[i][j]) )
//print error message, throw exception, break, ...
break;
else
theSum += theBlocks[i][j];
For more generic solution to work with more data types and more operations than addition, check this: How to detect integer overflow?
A solution would be using unsigned long long and if it exceeds its boundary too, you need to use third party libraries for big integers.
Like Mokhtar Ashour says, it's may be that the variable theSum overflows. Try making it either unsigned if no numbers are negative, or change the type from int (which is 32 bits) to long long (which is 64 bits).
I think it may be int overflow problem. to make sure, you may insert a condition after the inner loop finishes to see if your result exceeds the int range.
if(result>sizeof(int))
cout<<"hitting boundaries";
a better way to test if you exceed the int boundaries is to print the result after the inner loop ends and notice the result.
.if so, just use a bigger data type.

What's an efficient way to avoid integer overflow converting an unsigned int to int in C++?

Is the following an efficient and problem free way to convert an unsigned int to an int in C++:
#include <limits.h>
void safeConvert(unsigned int passed)
{
int variable = static_cast<int>(passed % (INT_MAX+1));
...
}
Or is there a better way?
UPDATE
As pointed out by James McNellis it is not undefined to assign an unsigned int > INT_MAX to an integer - rather this is implementation defined. As such the context here is now specifically on my preference is to ensure this integer resets to zero when the unsigned int exceeds INT_MAX.
Original Context
I have a number of unsigned int's used as counters, but want to pass them around as integers in a specific case.
Under normal operation these counts will remain within the bounds of INT_MAX. However to avoid running into undefined implementation specific behaviour should the abnormal (but valid) case occur I want some efficient conversion here.
This should also work:
int variable = passed & INT_MAX;
Under normal operation these counts will remain within the bounds of INT_MAX. However to avoid running into undefined behaviour should the abnormal (but valid) case occur I want some efficient conversion here.
Efficient conversion to what? If all the shared values for int and unsigned int correspond, and you want other unsigned values such as INT_MAX + 1 to each have distinct values, then you can only map them onto the negative integer values. This is done by default, and can be explicitly requested with static_cast<int>(my_unsigned). Otherwise, you could map them all to 0, or -1, or INT_MIN, or throw away the high bit... easiest way is simply: if (my_unsigned > INT_MAX) my_unsigned = XXX, or ...my_unsigned &= INT_MAX to clear the high bit. But will the called functions work properly if the int overflows? Perhaps a better solution would be to use 64-bit ints to begin with?