I have the following C++ code:
return lineNum >= startLineNum
&& lineNum <= startLineNum + lines.size() - 1;
Here, lineNum is an int, startLineNum is an int, lines is a std::vector<std::string>, and lines.size() is of type size_t.
When lineNum is 2, startLineNum is 0, and lines.size() is 0, the code returns true even though false was expected. These values were the values displayed in the debugger.
Even after adding parentheses where possible:
return ((lineNum >= startLineNum)
&& (lineNum <= (startLineNum + lines.size() - 1)));
the code still incorrectly returns true.
When I refactor the code into this form:
int start = startLineNum;
int end = startLineNum + lines.size() - 1;
return lineNum >= start && lineNum <= end;
it now returns false as expected.
What is going on here? I have never come across this kind of strangeness before.
lines.size() is more than likely an unsigned type. (If lines is a std::vector for example it's certainly unsigned.)
So due to the rules of argument promotion, and the fact that the terms in
startLineNum + lines.size() - 1;
are grouped from left to right, they are all converted to unsigned types.
This means that 0 + 0 - 1 is std::numeric_limits<decltype(lines.size())>::max() - a large number indeed, and lineNum is most likely less than it.
The rule of thumb: never use a negative when working with unsigned types, unless you really know what you're doing.
In your case, restate the problem to
lineNum < startLineNum + lines.size()
My guess would be that
lineNum <= startLineNum + lines.size() - 1;
is all unsigned types. linenum is 2, the other two are 0, and 0-1 in unsigned arithmetic is something VERY large (if 4 byte something above 4 billion).
Do instead
lineNum + 1 <= startLineNum + lines.size();
and all should be fine.
Related
I am unsure whether or not I better should have posted this question on codereview.stackexchange.com. Anyway, here we go ...
Please consider the following code snippet which is a literal (I have only changed the formatting) excerpt from here and has been printed (in stripped-down form) in the German computer magazine c't, issue 23/2019:
while (lo <= hi) {
std::streamoff pos = std::streamoff((uint64_t(lo) + uint64_t(hi)) / 2);
pos -= pos % std::streamoff(PasswordHashAndCount::size);
pos = std::max<int64_t>(0, pos);
phc.read(mInputFile, pos);
++nReads;
if (hash > phc.hash) {
lo = pos + std::streamoff(PasswordHashAndCount::size);
}
else if (hash < phc.hash) {
hi = pos - std::streamoff(PasswordHashAndCount::size);
}
else {
safe_assign(readCount, nReads);
return phc;
}
}
Why do we need the fourth line pos = std::max<int64_t>(0, pos);?
From the second line, we see that pos is equal or greater to 0, because it is the half of the sum of two numbers which themselves are of type uint64_t.
The third line can't make pos lower than 0. Proof:
For simplicity, replace pos by A and std::streamoff(PasswordHashAndCount::size) by B. Then the third line reads A -= A % B which is equivalent to A = A - (A % B), where A and B are integers, A being equal to or greater than 0, and B being greater than 0 (because ::size is always greater than 0).
First, if A < B, A % B = A. In this case, the third line becomes A = A - A, that is, A = 0.
Secondly, if A == B, A % B becomes A % A which is 0. Therefore, the third line becomes A = A - 0, which is equivalent to a null operation. In other words, A does not change in that case; notably, it remains 0 or greater than that.
Third, if A > B, A - (A % B) is greater than 0. This is because A % B is smaller than B, and thus, A - (A % B) is greater than A - B. The latter in turn is greater than 0, because the condition here was A > B.
Of course, the three cases A > B, A < B and A == B are all cases which can occur. In every case, the third line assigns a new value to A which is 0 or positive.
Coming back to the original variable naming, that means that pos is always 0 or greater than that after execution of the third line.
Given that, I don't understand what the fourth line does. After all, max(0, pos) is always equivalent to pos if pos is 0 or positive.
What am I missing? Is there an error in the reasoning above?
Let's consider what exactly it does:
std::streamoff pos = std::streamoff((uint64_t(lo) + uint64_t(hi)) / 2);
pos = std::max<int64_t>(0, pos);
std::streamoff is some implementation defined signed integer type. Let's consider a case where it is a 64 bit type or smaller: The value of pos will not be changed by the conversion to int64_t because the type is wider, nor when converting back in the assignment because the original value must have been representable.
Let's consider a case where std::streamoff is a 128 bit type or wider: The value comes from (uint64_t(lo) + uint64_t(hi)) / 2 which cannot exceed maximum of int64_t. Thus, the value cannot be changed by the conversion in this case either.
Thus, the use of int64_t has no effect in any case.
The third line can't make pow lower than 0
Is there an error in the reasoning above?
I cannot find any error.
Given that, I don't understand what the fourth line does.
The line has no effect at on the behaviour of the program at all. The program would have equivalent behaviour if the line was written:
;
Besides, on most systems that you find on desktop or server, std::streamoff and int64_t have the same number of bits.
I know that the evaluation of operands is from left to right and for the "&&" operand if the left one is false, the right should not be evaluated! but for this line of code with a vector it does not work like this,
suppose left =1 and v.size = 1; so we do not have v[1]. because there is only v[0] in the vector
if ((left <= (v.size() -1 )) && ( v[node].Value > v[left].Value))
{
TempMin = left;
}
So i expect that the right operand not be evaluated, but it gives me the 'out of range error'.
any ideas??
EDITED
v.size () is 1 and v.size() -1 =0.
I changed to code and find the problem and I think there is a problem with VISUAL STUDIO runtime debugger. because when I just run the code everything works great, but when I debug the code line by line the IF statement does not work properly
if (left <= v.size() -1 ) // first if
if (v[node].Value > v[left].Value) // right
TempMin = left;
in this situation the first if PASS and there is an error but if I change it to
if (left < v.size() ) // first if
or
int t = v.size() - 1;
if (left < t )
everything is ok. So it seems there is problem with (v.size() -1 )!!
Possible problems:
v.size() = 0
Then v.size() - 1 is size_t and equals 18446744073709551615 (2^64 - 1). So left <= 18446744073709551615 and you get out of range.
Solution:
left + 1 <= v.size() or left < v.size() instead of left <= v.size() - 1
v[node] gives you out of range.
Solution:
Add check for node
I am writing code in Hackerrank. And recently the problem said, convert decimal to base 2 and then count the max consecutive 1's in the binary number. And first I come with following solution. It works fine. But I do not understand the counting part of it, even though I wrote it.
The code is
int main(){
int n,ind=0, count=0, mmax=0;
char bin[100];
cin >> n;
while(n){
if(n%2==0) {
bin[ind]='0';
n = n / 2;
ind = ind + 1;
}
else if(n%2==1) {
bin[ind]='1';
n = n / 2;
ind = ind + 1;
}
}
for(int i=0; i<=(ind-1); i++){
if(bin[i] == '1' && bin[i+1] == '1'){
count++;
if(mmax < count)
mmax = count;
}
else
count=0;
}
cout << mmax + 1 << endl;
return 0;
}
In the above code, I guess that variable mmax will give me the max consecutive number of 1's but it gives me value that has (max consecutive - 1), So I just wrote like that and submitted the code. But I am curious about. why it is working that way. I am little bit of confused the way that code works like this.
Thanks
Lets say you have this binary sequence:
11110
Your code will compare starting from the first and second:
|11|110 1 && 1 -> max = 1
1|11|10 1 && 1 -> max = 2
11|11|0 1 && 1 -> max = 3
111|10| 1 && 0 -> max = 3
you can see, that although there are 4 1's you only do 3 comparisons, so your max will always be -1 of the actual max. You can fix this by adding mmax += 1 after your for loop.
Just a little bit of trace using small example will show why.
First, lets say there is only 1 '1' in your array.
Since you require both the current position and your next position to be '1', you will always get 0 for this case.
Let's say I have "11111". At the first '1', since next position is also '1', you increment count once. This repeats until 4th '1' and you increment your count 4 times in total so far. When you reach 5th '1', your next position is not '1', thus your count stops at 4.
In general, your method is like counting gaps between fingers, given 5 fingers, you get 4 gaps.
Side note: your code will fail for the case when there is no '1' in your array.
I'm currently doing a problem that's similar to the maximum contiguous sub-array problem. However, instead of finding just one contiguous sub-array, I can find up to two non-overlapping contiguous subarrays.
For instance for the test case below, the answer is 20 since we can take everything but -20.
5 3 -20 4 8
To do this, I implemented the following code:
long long n, nums[500500], dp[500500][2][3];
long long best(int numsLeft, int beenTaking, int arrLeft) {
if (arrLeft < 0 || numsLeft < 0) return 0;
if (dp[numsLeft][beenTaking][arrLeft] != -1)
return dp[numsLeft][beenTaking][arrLeft];
if (beenTaking) {
// continue Taking
long long c1 = best(numsLeft - 1, beenTaking, arrLeft) + nums[numsLeft];
// stop Taking
long long c2 = best(numsLeft - 1, 0, arrLeft);
return dp[numsLeft][beenTaking][arrLeft] = max(c1, c2);
} else {
// continue not Taking
long long c1 = best(numsLeft - 1, beenTaking, arrLeft);
// start Taking
long long c2 = best(numsLeft - 1, 1, arrLeft - 1) + nums[numsLeft];
return dp[numsLeft][beenTaking][arrLeft] = max(c1,c2);
}
}
This is the function call:
cout << best(n - 1, 0, 2) << endl;
The dp array has been -1 filled before the function call. The nums array contain n elements and is zero-indexed.
Ideone.com link is this: http://ideone.com/P5PB7h
While my code does work for the sample test-case shown above, it fails for some other test-cases (that are not available to me). Are there any edge cases that are not being caught by my code? Where am I going wrong? Thank you for the help.
I tried coming up with a few such edge cases, but am unable to do so.
The problem seems to be on the following lines:
if (beenTaking) {
// continue Taking
long long c1 = best(numsLeft - 1, beenTaking, arrLeft) + nums[numsLeft];
...
} else {
...
}
Adding best(numsLeft - 1, 1, arrLeft) without decrementing arrLeft implies that the "best" results from the first numsLeft - 1 values in nums[] happens at the end of nums[] (at index numsLeft - 1). This may not be true.
The code will therefore likely fail when there are more than 2 positive ranges separated by negative values.
Also, the dp array should be initialized to something clearly out of range, like LLONG_MIN, rather than -1, which could be a legitimate sum.
The project I am working on needs to find some way of verifying that a variable after the modulus operation is either number != 0, number > 0, or number < (0 < x < 1). I have the first two understood, however employing the mod operator to accomplish the third is difficult.
Essentially what I am looking to do is to be able to catch a value similar to something like this:
a) 2 % 6
b) flag it and store the fact that .333 is less than 1 in a variable (bool)
c) perform a follow up action on the basis that the variable returned a value less than 1.
I have a feeling that the mod operator cannot perform this by itself. I'm looking for a way to utilize its ability to find remainders in order to produce a result.
edit: Here is some context. Obveously the below code will not give me what I want.
if (((inGameTotalCoins-1) % (maxPerTurn+1)) < 0){
computerTakenCoins = (inGameTotalCoins - 1);
inGameTotalCoins = 1;
The quotient is 0(2/6) with the fractional part discarded.The fractional part is .3333 ... So you are basically talking about the fractional part of the quotient , not the modulus value. Modulus can be calculated as follows :
(a / b) * b + (a % b) = a
(2 / 6) * 6 + (2 % 6) = 2
0 * 6 + (2 % 7) = 2
(2 % 6) = 2
*6 goes into 2 zero times with 2 left over.
How about this:-
int number1 = 2;
int number2 = 6;
float number3 = static_cast<float>(number1) / static_cast<float>(number2);
bool isfraction = number3 > 0 && number3 < 1;
if(isfraction){
std :: cout << "true\n" << number3;
}
else{
std :: cout << "false" << number3;
}
number != 0 includes number > 0 and number < (0 x < 1). And number > 0 includes number < (0 x < 1). Generally we do not classify so. For example, people classify number > 0, number == 0 and number < 0.
If you do the modulous operation, you get remainder. Remainder's definition is not one thing. You can see it at https://en.m.wikipedia.org/wiki/Remainder