IF,ELSE statement / Loop and variables assignment: code optimization best practices - performance

I have some simple and very basic questions here but yet I would like to have the wind up once forever so I decided to ask for.
Ok, here comes the code and the question within:
is something like
for (n=0;n<length;++n) countsc[n]=0;
countsc[x]=1; // x is something
better than something like
for (n=0;n<length;++n) {
if (n != x) countsc[n]=0;
else countsc[n]=1;
}
or also
for (n=0;n<length;++n) countsc[n]=(n != x ? 0 : 1);
in terms of performance and optimization (speed, cpu and memory usage)?
How would it be the convenient way one should measure it, for example, with Javascript and/or with PHP? Would the answer be generally valid for all programming languages or it may differ?
In a similar way, is something like
a=0;
if (condition == true) a=1;
generally better than
if (condition == true) a=1;
else a=0;
or also
a = (condition == true ? 1 : 0);
when condition is usually false?

Probably not the answer you're looking for, but in general, I don't think there would be a general way to figure this out from static analysis of code. This is not only going to vary by language, but also possibly by architecture you run it on. I suspect any half-decent compiler should optimize these so there is little/no difference, but that may be less likely for interpreted languages.
If it really is a performance critical section of code (and you will only know that by profiling), then the best answer you will get will be by profiling and comparing the two candidate code sections on your target architecture, using the relevant language.

Depending on the quality of the compiler (or interpreter, if appropriate),
for (n=0;n<length;++n) countsc[n]=0;
countsc[x]=1;
is easier to optimize, since there are no branches to (mis)predict. The minor duplication of setting countsc[x] twice is trivial compared to need to test n each iteration and the penalty for a missed branch prediction inside the loop of
for (n=0;n<length;++n) {
if (n != x) countsc[n]=0;
else countsc[n]=1;
}
In terms of branch prediction, your third example with the ternary operator is identical to the second.
However, unless this is a tight inner loop that is either executed frequently and/or for very large values of length, it's unlikely to matter which approach you use looking at the overall running time of your program.

for (n=0;n<length;++n) countsc[n]=0;
countsc[x]=1;
is the more performant option, assuming comparison and assignment have roughly the same cost.
Similarly,
if (condition) a=1; // boolean == true is not pretty
else a=0;
should be more performant; you only have one assignment and one jump, while you have up to two assignments and one jump with the alternative version. This version
a = (condition == true ? 1 : 0);
should be just as good, I expect it is compiled to the same code as the if-else version.

I would think
for (n = 0; n < x; ++n)
countsc[n] = 0;
countsc[x] = 1;
for (n = x + 1; n < length; ++n)
countsc[n] = 0;
Would be better than using the conditional, and you avoid rewriting your countsc[x]. Of course, everything is O(n) and you won't notice any change in the speed in your program.

Related

Difference in performance between the following two implementations of binary search

I came across these two implementations of binary search in the book "Competitive Programmer's Handbook" https://cses.fi/book/book.pdf.
Method 1:
int a = 0, b = n-1;
while (a <= b) {
int k = (a+b)/2;
if (array[k] == x) {
// x found at index k
}
if (array[k] > x)
b = k-1;
else
a = k+1;
}
Method 2:
int k = 0;
for (int b = n/2; b >= 1; b /= 2){
while (k+b < n && array[k+b] <= x)
k += b;
}
if (array[k] == x){
// x found at index k
}
I guess method 2 is not exactly binary search.
I understand that Both method 1 and method 2 have O(log n) complexity. Also the code for method 2 is simpler and therefore might result in fewer bugs.
My questions are:
Is there any improvement in performance when method-2 is used?
Does method-2 have any other advantage?
For such short code and so few differences, it is impossible to do any prediction. The time performance will depend on how the compiler optimizes, but also on the distribution of the keys in the array (in particular, the probability of a hit rather than a miss).
I disagree with all comments "against" the second method (even claimed buggy when it is perfectly correct). It is based on a principle that potentially makes it better: there's only one test in the body of the loop.
Having a comparison for equality (Method 1) gives the false feeling that the algorithm will terminate early when the key is found and make the search faster*. But this is not so true, because for half of the keys the full depth of the decision tree is anyway necessary, and this not counter-balanced by the fact that there are two comparisons instead of one.
*In fact, you just spare one test on average !
Only benchmarking can tell you if one of the methods is faster with particular test cases. My bet is that the distributions of the running times overlap a lot. (Not counting that it is virtually impossible to benchmark such a fast algorithm in a way that is representative of its behavior in real context.)
Last comment: the method 2 is a binary search, while in fact method 1 is ternary !

What is the purpose of this method?

in an interview question, I got asked the following:
What is the purpose of the below method, and how can we rewrite it?
public int question_1(int a, int b)
{
while (a > b)
{
a -= b;
}
return a;
}
at first I thought it is equivalent to a%b, but it is not since it is "while (a > b)" and not "while ( a >= b)".
Thanks
Honestly, it's impossible to know the purpose of a method just by reading its implementation, even if we assume that it's bug-free.
But, we can start by documenting its behaviors:
If b is positive:
If a is positive, the method returns the least positive integer that is congruent to a modulo b. (For example, given 15 and 10, it will return 5; given 30 and 10, it will return 10.)
Otherwise, the method returns a.
If b is zero:
If a is positive, the method loops forever.
Otherwise, the method returns a.
If b is negative:
If a ≤ b, the method returns a.
Otherwise, the method's behavior depends on the language, since it will increase a until it's no longer greater than b. If the language defines integer arithmetic using "wraparound" rules, then the method will loop for a long time, then finally return a very negative number (unless b is itself very negative, in which case, depending on the value of a, the function might loop forever).
and given these, we can infer that the behaviors with zero and negative numbers are bizarre enough that the method is probably actually only intended to be used with positive numbers. So its behavior can be summarized as:
If a and b are both positive, then the method returns the least positive integer that is congruent to a modulo b.
If the above inference is correct, then the method can be rewritten as:
public int question_1(int a, int b) {
if (a <= 0 || b <= 0)
throw new IllegalArgumentException();
return (a - 1) % b + 1;
}
I would guess that its purpose is to compute a%b for positive ints, and that it has a bug.
If I saw this in production, I would have to check the uses of this function to see if question_1(n,n) == n is really correct. If so, I'd add a comment indicating why that is so. Otherwise I'd fix it.
It either case, it could be rewritten to use the % operator instead of a loop. If it's correct, it could be rewritten like this:
public int question_1(int a, int b)
{
if (a>b)
{
a = ((a-1)%b) + 1;
}
return a;
}
This is not the same in its handling of negative numbers, though, so again you'd have to check to make sure that's OK.
The reason I provide this answer when #ruakh has already provided such a carefully considered answer is that this is an interview question, so it's best if you take the opportunity to show how you would approach a problem like this on the job.
You don't really want to give the impression that you would spend a long time and a lot of effort thinking carefully about such a simple problem -- if you have to spend that much effort to solve a simple problem, imagine what you would spend on a big one!
At the same time, you want to demonstrate that you recognize the possible bug, and take the initiative to fix it or to spare future engineers the same task.

Is there any clever way to determine whether a point is in a rectangle?

I want to calculate whether a point, (x,y), is inside a rectangle which is determined by two points, (a,b) and (c,d).
If a<=c and b<=d, then it is simple:
a<=x&&x<=c&&b<=y&&y<=d
However, since it is unknown whether a<=c or b<=d, the code should be
(a<=x&&x<=c||c<=x&&x<=a)&&(b<=y&&y<=d||d<=y&&y<=b)
This code may work, but it is too long. I can write a function and use it, but I wonder if there's shorter way (and should be executed very fast - the code is called a lot) to write it.
One I can imagine is:
((c-x)*(x-a)>=0)&&((d-y)*(y-b)>=0)
Is there more clever way to do this?
(And, is there any good way to iterate from a from c?)
Swap the variables as needed so that a = xmin and b = ymin:
if a > c: swap(a,c)
if b > d: swap(b,d)
a <= x <= c and b <= y <= d
Shorter but slightly less efficient:
min(a,c) <= x <= max(a,c) and min(b,d) <= y <= max(b,d)
As always when optimizing you should profile the different options and compare hard numbers. Pipelining, instruction reordering, branch prediction, and other modern day compiler/processor optimization techniques make it non-obvious whether programmer-level micro-optimizations are worthwhile. For instance it used to be significantly more expensive to do a multiply than a branch, but this is no longer always the case.
I like the this:
((c-x)*(x-a)>=0)&&((d-y)*(y-b)>=0)
but with more whitespace and more symmetry:
(c-x)*(a-x) <= 0 && (d-y)*(b-y) <= 0
It's mathematically elegant, and probably the fastest too. You will need to measure to really determine which is the fastest. With modern pipelined processors, I would expect that straight-line code with the minimum number of operators will run fastest.
While sorting the (a, b) and (c, d) pairs as suggested in the accepted answer is probably the best solution in this case, an even better application of this method would probably be to elevate the a < b and c < d requirement to the level of the program-wide invariant. I.e. require that all rectangles in your program are created and maintained in this "normalized" form from the very beginning. Thus, inside your point-in-rectangle test function you should simply assert that a < b and c < d instead of wasting CPU resources on actually sorting them in every call.
Define intermediary variables i = min(a,b), j = min(c,d), k = max(a,b), l = max(c,d)
Then you only need i<=x && x<=k && j<=y && y<=l.
EDIT: Mind you, efficiency-wise it's probably better to use your "too long" code in a function.

Tail-recursive pow() algorithm with memoization?

I'm looking for an algorithm to compute pow() that's tail-recursive and uses memoization to speed up repeated calculations.
Performance isn't an issue; this is mostly an intellectual exercise - I spent a train ride coming up with all the different pow() implementations I could, but was unable to come up with one that I was happy with that had these two properties.
My best shot was the following:
def calc_tailrec_mem(base, exp, cache_line={}, acc=1, ctr=0):
if exp == 0:
return 1
elif exp == 1:
return acc * base
elif exp in cache_line:
val = acc * cache_line[exp]
cache_line[exp + ctr] = val
return val
else:
cache_line[ctr] = acc
return calc_tailrec_mem(base, exp-1, cache_line, acc * base, ctr + 1)
It works, but it doesn't memoize the results of all calculations - only those with exponents 1..exp/2 and exp.
You'll get better performance if you use the successive squaring technique described in SICP section 1.2.4 Exponentiation. It doesn't use memoization, but the general approach is O(log n) instead of O(n), so you should still see an improvement.
I talk about the solution to the iterative process from exercise 1.16 here.
I don't think you're recording the correct thing in your cache, the mapping changed when you call it with different arguments.
I think you need to have a cache of (base,exp) -> pow(base,exp).
I understand what ctr is for, and why only half of what you expect is recorded.
Consider calc_tailrec_mem(2,4): First level, pow(2,1) is recorded as 2, the next level = calc_tailrec_mem(2,3,...), and pow(2,2) is recorded. The next level is calc_tailrec_mem(2,2,...), but that is already saved in the cache, so the recursion stops.
The function is very confusing because it's caching something completely different from what it's supposed to be calculating, due to the acculumator and ctr.
This is way too late, but anyone out there looking for the answer, here it is:
int powMem(int base,int exp){
//initializes once and for all
static map<int,int> memo;
//base case to stop the recursion
if(exp <= 1) return base;
//check if the value is already calculated before. If yes just return it.
if(memo.find(exp) != memo.end())
return memo[exp];
//else just find it and then store it in memo for further use.
int x = powMem(base,exp/2);
memo[exp] = x*x;
//return the answer
return memo[exp];
}
This uses the memo array - a map , to be exact - to store the already calculated values.

Should one use < or <= in a for loop [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
If you had to iterate through a loop 7 times, would you use:
for (int i = 0; i < 7; i++)
or:
for (int i = 0; i <= 6; i++)
There are two considerations:
performance
readability
For performance I'm assuming Java or C#. Does it matter if "less than" or "less than or equal to" is used? If you have insight for a different language, please indicate which.
For readability I'm assuming 0-based arrays.
UPD: My mention of 0-based arrays may have confused things. I'm not talking about iterating through array elements. Just a general loop.
There is a good point below about using a constant to which would explain what this magic number is. So if I had "int NUMBER_OF_THINGS = 7" then "i <= NUMBER_OF_THINGS - 1" would look weird, wouldn't it.
The first is more idiomatic. In particular, it indicates (in a 0-based sense) the number of iterations. When using something 1-based (e.g. JDBC, IIRC) I might be tempted to use <=. So:
for (int i=0; i < count; i++) // For 0-based APIs
for (int i=1; i <= count; i++) // For 1-based APIs
I would expect the performance difference to be insignificantly small in real-world code.
Both of those loops iterate 7 times. I'd say the one with a 7 in it is more readable/clearer, unless you have a really good reason for the other.
I remember from my days when we did 8086 Assembly at college it was more performant to do:
for (int i = 6; i > -1; i--)
as there was a JNS operation that means Jump if No Sign. Using this meant that there was no memory lookup after each cycle to get the comparison value and no compare either. These days most compilers optimize register usage so the memory thing is no longer important, but you still get an un-required compare.
By the way putting 7 or 6 in your loop is introducing a "magic number". For better readability you should use a constant with an Intent Revealing Name. Like this:
const int NUMBER_OF_CARS = 7;
for (int i = 0; i < NUMBER_OF_CARS; i++)
EDIT: People aren’t getting the assembly thing so a fuller example is obviously required:
If we do for (i = 0; i <= 10; i++) you need to do this:
mov esi, 0
loopStartLabel:
; Do some stuff
inc esi
; Note cmp command on next line
cmp esi, 10
jle exitLoopLabel
jmp loopStartLabel
exitLoopLabel:
If we do for (int i = 10; i > -1; i--) then you can get away with this:
mov esi, 10
loopStartLabel:
; Do some stuff
dec esi
; Note no cmp command on next line
jns exitLoopLabel
jmp loopStartLabel
exitLoopLabel:
I just checked and Microsoft's C++ compiler does not do this optimization, but it does if you do:
for (int i = 10; i >= 0; i--)
So the moral is if you are using Microsoft C++†, and ascending or descending makes no difference, to get a quick loop you should use:
for (int i = 10; i >= 0; i--)
rather than either of these:
for (int i = 10; i > -1; i--)
for (int i = 0; i <= 10; i++)
But frankly getting the readability of "for (int i = 0; i <= 10; i++)" is normally far more important than missing one processor command.
† Other compilers may do different things.
I always use < array.length because it's easier to read than <= array.length-1.
also having < 7 and given that you know it's starting with a 0 index it should be intuitive that the number is the number of iterations.
Seen from an optimizing viewpoint it doesn't matter.
Seen from a code style viewpoint I prefer < . Reason:
for ( int i = 0; i < array.size(); i++ )
is so much more readable than
for ( int i = 0; i <= array.size() -1; i++ )
also < gives you the number of iterations straight away.
Another vote for < is that you might prevent a lot of accidental off-by-one mistakes.
#Chris, Your statement about .Length being costly in .NET is actually untrue and in the case of simple types the exact opposite.
int len = somearray.Length;
for(i = 0; i < len; i++)
{
somearray[i].something();
}
is actually slower than
for(i = 0; i < somearray.Length; i++)
{
somearray[i].something();
}
The later is a case that is optimized by the runtime. Since the runtime can guarantee i is a valid index into the array no bounds checks are done. In the former, the runtime can't guarantee that i wasn't modified prior to the loop and forces bounds checks on the array for every index lookup.
It makes no effective difference when it comes to performance. Therefore I would use whichever is easier to understand in the context of the problem you are solving.
I prefer:
for (int i = 0; i < 7; i++)
I think that translates more readily to "iterating through a loop 7 times".
I'm not sure about the performance implications - I suspect any differences would get compiled away.
In C++, I prefer using !=, which is usable with all STL containers. Not all STL container iterators are less-than comparable.
In Java 1.5 you can just do
for (int i: myArray) {
...
}
so for the array case you don't need to worry.
I don't think there is a performance difference. The second form is definitely more readable though, you don't have to mentally subtract one to find the last iteration number.
EDIT: I see others disagree. For me personally, I like to see the actual index numbers in the loop structure. Maybe it's because it's more reminiscent of Perl's 0..6 syntax, which I know is equivalent to (0,1,2,3,4,5,6). If I see a 7, I have to check the operator next to it to see that, in fact, index 7 is never reached.
I'd say use the "< 7" version because that's what the majority of people will read - so if people are skim reading your code, they might interpret it wrongly.
I wouldn't worry about whether "<" is quicker than "<=", just go for readability.
If you do want to go for a speed increase, consider the following:
for (int i = 0; i < this->GetCount(); i++)
{
// Do something
}
To increase performance you can slightly rearrange it to:
const int count = this->GetCount();
for (int i = 0; i < count; ++i)
{
// Do something
}
Notice the removal of GetCount() from the loop (because that will be queried in every loop) and the change of "i++" to "++i".
Edsger Dijkstra wrote an article on this back in 1982 where he argues for lower <= i < upper:
There is a smallest natural number. Exclusion of the lower bound —as in b) and d)— forces for a subsequence starting at the smallest natural number the lower bound as mentioned into the realm of the unnatural numbers. That is ugly, so for the lower bound we prefer the ≤ as in a) and c). Consider now the subsequences starting at the smallest natural number: inclusion of the upper bound would then force the latter to be unnatural by the time the sequence has shrunk to the empty one. That is ugly, so for the upper bound we prefer < as in a) and d). We conclude that convention a) is to be preferred.
First, don't use 6 or 7.
Better to use:
int numberOfDays = 7;
for (int day = 0; day < numberOfDays ; day++){
}
In this case it's better than using
for (int day = 0; day <= numberOfDays - 1; day++){
}
Even better (Java / C#):
for(int day = 0; day < dayArray.Length; i++){
}
And even better (C#)
foreach (int day in days){// day : days in Java
}
The reverse loop is indeed faster but since it's harder to read (if not by you by other programmers), it's better to avoid in. Especially in C#, Java...
I agree with the crowd saying that the 7 makes sense in this case, but I would add that in the case where the 6 is important, say you want to make clear you're only acting on objects up to the 6th index, then the <= is better since it makes the 6 easier to see.
Way back in college, I remember something about these two operations being similar in compute time on the CPU. Of course, we're talking down at the assembly level.
However, if you're talking C# or Java, I really don't think one is going to be a speed boost over the other, The few nanoseconds you gain are most likely not worth any confusion you introduce.
Personally, I would author the code that makes sense from a business implementation standpoint, and make sure it's easy to read.
This falls directly under the category of "Making Wrong Code Look Wrong".
In zero-based indexing languages, such as Java or C# people are accustomed to variations on the index < count condition. Thus, leveraging this defacto convention would make off-by-one errors more obvious.
Regarding performance: any good compiler worth its memory footprint should render such as a non-issue.
As a slight aside, when looping through an array or other collection in .Net, I find
foreach (string item in myarray)
{
System.Console.WriteLine(item);
}
to be more readable than the numeric for loop. This of course assumes that the actual counter Int itself isn't used in the loop code. I do not know if there is a performance change.
There are many good reasons for writing i<7. Having the number 7 in a loop that iterates 7 times is good. The performance is effectively identical. Almost everybody writes i<7. If you're writing for readability, use the form that everyone will recognise instantly.
I have always preferred:
for ( int count = 7 ; count > 0 ; -- count )
Making a habit of using < will make it consistent for both you and the reader when you are iterating through an array. It will be simpler for everyone to have a standard convention. And if you're using a language with 0-based arrays, then < is the convention.
This almost certainly matters more than any performance difference between < and <=. Aim for functionality and readability first, then optimize.
Another note is that it would be better to be in the habit of doing ++i rather than i++, since fetch and increment requires a temporary and increment and fetch does not. For integers, your compiler will probably optimize the temporary away, but if your iterating type is more complex, it might not be able to.
Don't use magic numbers.
Why is it 7? ( or 6 for that matter).
use the correct symbol for the number you want to use...
In which case I think it is better to use
for ( int i = 0; i < array.size(); i++ )
The '<' and '<=' operators are exactly the same performance cost.
The '<' operator is a standard and easier to read in a zero-based loop.
Using ++i instead of i++ improves performance in C++, but not in C# - I don't know about Java.
As people have observed, there is no difference in either of the two alternatives you mentioned. Just to confirm this, I did some simple benchmarking in JavaScript.
You can see the results here. What is not clear from this is that if I swap the position of the 1st and 2nd tests, the results for those 2 tests swap, this is clearly a memory issue. However the 3rd test, one where I reverse the order of the iteration is clearly faster.
As everybody says, it is customary to use 0-indexed iterators even for things outside of arrays. If everything begins at 0 and ends at n-1, and lower-bounds are always <= and upper-bounds are always <, there's that much less thinking that you have to do when reviewing the code.
Great question. My answer: use type A ('<')
You clearly see how many iterations you have (7).
The difference between two endpoints is the width of the range
Less characters makes it more readable
You more often have the total number of elements i < strlen(s) rather than the index of the last element so uniformity is important.
Another problem is with this whole construct. i appears 3 times in it, so it can be mistyped. The for-loop construct says how to do instead of what to do. I suggest adopting this:
BOOST_FOREACH(i, IntegerInterval(0,7))
This is more clear, compiles to exaclty the same asm instructions, etc. Ask me for the code of IntegerInterval if you like.
So many answers ... but I believe I have something to add.
My preference is for the literal numbers to clearly show what values "i" will take in the loop. So in the case of iterating though a zero-based array:
for (int i = 0; i <= array.Length - 1; ++i)
And if you're just looping, not iterating through an array, counting from 1 to 7 is pretty intuitive:
for (int i = 1; i <= 7; ++i)
Readability trumps performance until you profile it, as you probably don't know what the compiler or runtime is going to do with your code until then.
You could also use != instead. That way, you'll get an infinite loop if you make an error in initialization, causing the error to be noticed earlier and any problems it causes to be limitted to getting stuck in the loop (rather than having a problem much later and not finding it).
I think either are OK, but when you've chosen, stick to one or the other. If you're used to using <=, then try not to use < and vice versa.
I prefer <=, but in situations where you're working with indexes which start at zero, I'd probably try and use <. It's all personal preference though.
Strictly from a logical point of view, you have to think that < count would be more efficient than <= count for the exact reason that <= will be testing for equality as well.

Resources