C# which is faster do/while or for? - c#

I have a C# .NET 2.0 script and I want to know why the following code would be faster than a do while loop of the same kind.
private double getStop(double avgPrice, bool longTrading)
{
double stopS = 0.0;
double stopL = 0.0;
for (int i = 0; i < 13; i++)
{
if (i == 0 || i == 12)
{
stopS = 0.0;
stopL = 0.0;
}
else
{
if ((lines[i] - ((lines[i] - lines[i - 1]) / 2)) < avgPrice && avgPrice < (lines[i + 1] - ((lines[i + 1] - lines[i]) / 2)))
{
if (avgPrice < lines[i])
{
stopL = (lines[i] - ((lines[i] - lines[i - 1]) / 2));
stopS = lines[i];
} else {
stopL = lines[i];
stopS = (lines[i + 1] - ((lines[i + 1] - lines[i]) / 2));
}
}
}
}
if (longTrading)
{
return stopL;
} else {
return stopS;
}
}
Also, would it be faster just to explicitly state each if statement instead of doing them inside of a for loop?
Being that this was answered so fast, why would this run far slower than the above code?
private double getStop(double avgPrice, bool longTrading)
{
double stopS = 0.0;
double stopL = 0.0;
for (int i = 0; i < 13; i++)
{
if (i == 0 || i == 12)
{
stopS = 0.0;
stopL = 0.0;
skip = true;
}
if (!skip && (lines[i] - ((lines[i] - lines[i - 1]) / 2)) < avgPrice && avgPrice < (lines[i + 1] - ((lines[i + 1] - lines[i]) / 2)))
{
if (avgPrice < lines[i])
{
stopL = (lines[i] - ((lines[i] - lines[i - 1]) / 2));
stopS = lines[i];
} else {
stopL = lines[i];
stopS = (lines[i + 1] - ((lines[i + 1] - lines[i]) / 2));
}
}
}
skip = false;
}
if (longTrading)
{
return stopL;
} else {
return stopS;
}
}

The performance difference should be negligible, but the for loop is clearer so I would go with that.

They should be essentially equivalent. Your 'for' loop gets evaluated as:
int i = 0;
while (i < 13)
{
//all other stuff
i++;
};

loop variations aren't too much different, it depends on the context and the programming language.
But my opinion is, for statement don't do until the constaint(s) is/are matched, therefore it should be faster than do/while.

Related

How to overcome stack overflow exception in c# while calling a recursive function

I am doing a recursive program and during the execution of a recursive function it shows stack overflow error. I cannot proceed without completing this recursive function. Please some one help me...
This is the code that i have done:
public void blob(int k, int l, int[,] MV1)
{
while (true)
{
if ((MV1[k, l] == 1) && (status[k, l] != 1))
{
count = count + 1;
if (count < 6000)
{
if (k < xmin)
{
X[Xr, 0] = k;
xmin = k;
}
if (l < ymin)
{
Y[Yr, 0] = l;
ymin = l;
}
if (k > xmax)
{
X[Xr, 1] = k;
xmax = k;
}
if (l > ymax)
{
Y[Yr, 1] = l;
ymax = l;
}
status[k, l] = 1;
if (l != (MV1.Length / MV1.GetLength(0)) - 1)
{
blob(k, l + 1, MV1);
}
if ((l != 0))
{
blob(k, l - 1, MV1);
}
if (k != MV1.Length - 1)
{
blob(k + 1, l, MV1);
}
if ((k != 0))
{
blob(k - 1, l, MV1);
}
}
}
The problem is your method never exits the while loop because you have while (true). Therefore, your recursive algorithm keeps calling itself deeper and deeper until it runs out of space on the stack.
You need to make it so your loop exits at some point, either from within using return or preferably with a better condition in your while statement.
Note, it's generally considered bad practice to use while (true). You want to avoid doing so unless absolutely necesssary.

Big O Notation of this BinaryHeap code

I'm trying to determine the Big O notation of two methods that are based on Jim Mischel's BinaryHeap class.
public void Add(T item) {
int i = _items.Count;
_items.Add(item);
while (i > 0 && _items[(i - 1) / 2].CompareTo(item) > 0) {
_items[i] = _items[(i - 1) / 2];
i = (i - 1) / 2;
}
_items[i] = item;
}
public T Remove() {
T firstItem = _items[0];
T tempItem = _items[_items.Count - 1];
_items.RemoveAt(_items.Count - 1);
if (_items.Count > 0) {
int i = 0;
while (i < _items.Count / 2) {
int j = (2 * i) + 1;
if ((j < _items.Count - 1) && (_items[j].CompareTo(_items[j + 1]) > 0)) ++j;
if (_items[j].CompareTo(tempItem) >= 0) break;
_items[i] = _items[j];
i = j;
}
_items[i] = tempItem;
}
return firstItem;
}
For the Add method, I believe it's O(log(n)) since the loop appears to be of the form:
for(int i = n; i > 0; i=(i-1)/2);
And for the Remove method, I believe it's O(log(log(n)) since the loop appears to be of the form:
for(int i=0; i < n/2; i = (2*i)+1);
Is this correct?

Regex or string compare with allowance of error

I'm trying to do a string compare in C# with some allowance for error. For example, if my search term is "Welcome", but if my comparison string (generated through OCR) is "We1come" and my error allowance is 20%, that should match. That part isn't so difficult using something like the Levenshtein algorithm. The hard part is making it work within a larger block of text, like a regular expression. For example, maybe my OCR result is "Hello. My name is Ben. We1come to my StackOverflow question.", I would like to pick out that We1come as a good result compared to my search term.
Took quite a while, but this works well. Fun problem :)
string PossibleString = PossibleString.ToString().ToLower();
string StaticText = StaticText.ToLower();
decimal PossibleStringLength = (PossibleString.Length);
decimal StaticTextLength = (StaticText.Length);
decimal NumberOfErrorsAllowed = Math.Round((StaticTextLength * (ErrorAllowance / 100)), MidpointRounding.AwayFromZero);
int LevenshteinDistance = LevenshteinAlgorithm(StaticText, PossibleString);
string PossibleResult = string.Empty;
if (LevenshteinDistance == PossibleStringLength - StaticTextLength)
{
// Perfect match. no need to calculate.
PossibleResult = StaticText;
}
else
{
int TextLengthBuffer = (int)StaticTextLength - 1;
int LowestLevenshteinNumber = 999999;
for (int i = 0; i < 3; i++) // Check for best results with same amount of characters as expected, as well as +/- 1
{
for (int e = TextLengthBuffer; e <= (int)PossibleStringLength; e++)
{
string possibleResult = (PossibleString.Substring((e - TextLengthBuffer), TextLengthBuffer));
int lAllowance = (int)(Math.Round((possibleResult.Length - StaticTextLength) + (NumberOfErrorsAllowed), MidpointRounding.AwayFromZero));
int lNumber = LevenshteinAlgorithm(StaticText, possibleResult);
if (lNumber <= lAllowance && ((lNumber < LowestLevenshteinNumber) || (TextLengthBuffer == StaticText.Length && lNumber <= LowestLevenshteinNumber)))
{
PossibleResult = possibleResult;
LowestLevenshteinNumber = lNumber;
}
}
TextLengthBuffer++;
}
}
public static int LevenshteinAlgorithm(string s, string t)
{
int n = s.Length;
int m = t.Length;
int[,] d = new int[n + 1, m + 1];
if (n == 0)
{
return m;
}
if (m == 0)
{
return n;
}
for (int i = 0; i <= n; d[i, 0] = i++)
{
}
for (int j = 0; j <= m; d[0, j] = j++)
{
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
d[i, j] = Math.Min(
Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
d[i - 1, j - 1] + cost);
}
}
return d[n, m];
}
If it is somehow predictable how the OCR can miss letters, I would replace the letters in the search with misses.
If the search is Welcome, the regex would be (?i)We[l1]come.

Argument out of range exception thrown

I saw this function on Percentile calculation, so I copied it and pasted it into the compiler, and it gives me an OutOfRange exception at
else
{
int k = (int)n;
double d = n - k;
return sequence[k - 1] + d * (sequence[k] - sequence[k - 1]);//EXCEPTION
}
What could be the source of the problem, and how do I solve it?
Function:
public double Percentile(double[] sequence, double excelPercentile)
{
Array.Sort(sequence);
int N = sequence.Length;
double n = (N - 1) * excelPercentile + 1;
// Another method: double n = (N + 1) * excelPercentile;
if (n == 1d) return sequence[0];
else if (n == N) return sequence[N - 1];
else
{
int k = (int)n;
double d = n - k;
return sequence[k - 1] + d * (sequence[k] - sequence[k - 1]);
}
}
The issue is that k is a number larger than the number of items in the array.
As was mentioned, the function is designed to work with values between 0 and 1. Restricting the input should correct the problem.
public double Percentile(double[] sequence, double excelPercentile)
{
//if(excelPercentile > 1)
//excelPercentile = 1;
//else if(excelPercentile < 0)
//excelPercentile = 0;
//Depending on how you validate the input you can assume that it's a whole number percentage. Then you only need to check for the number to be between 0 and 100
if(excelPercentile > 100)
excelPercentile = 100;
else if(excelPercentile < 0)
excelPercentile = 0;
excelPercentile /= 100;
Array.Sort(sequence);
int N = sequence.Length;
double n = (N - 1) * excelPercentile + 1;
// Another method: double n = (N + 1) * excelPercentile;
if (n == 1d) return sequence[0];
else if (n == N) return sequence[N - 1];
else
{
int k = (int)n;
double d = n - k;
return sequence[k - 1] + d * (sequence[k] - sequence[k - 1]);
}
}

Can anyone spot the bug in my Damerau-Levenshtein Distance implementation?

I've got a funky bug that's driving me nuts. Can anyone help me find it? Try calling the function with two words that differ only by a missing last character ("garble" vs "garbl"). The function is returning 0 instead of the expected 1. It's supposed to return 1, right?
I've tried fiddling with the array bounds but that's only causing IndexOutOfRangeExceptions.
public static class FuzzyStringMatcher
{
private const int DELETION = 0;
private const int INSERTION = 1;
private const int SUBSTITUTION = 2;
private const int TRANSPOSITION = 3;
private const int COST_OF_DELETION = 1;
private const int COST_OF_INSERTION = 1;
private const int COST_OF_TRANSPOSITION = 1;
private const int COST_OF_SUBSTITUTION = 1;
public static int Compute_DamerauLevenshtein_Distance(string a, string b)
{
int[,] rows = new int[a.Length + 1, b.Length + 1];
int cost_ratio;
int[] calculations = new int[4];
//
// Init the array
//
for (int i = 0; i < rows.GetUpperBound(0); i++)
rows[i, 0] = i;
for (int i = 0; i < rows.GetUpperBound(1); i++)
rows[0, i] = i;
for (int aidx = 1; aidx < rows.GetUpperBound(0); aidx++)
{
for (int bidx = 1; bidx < rows.GetUpperBound(1); bidx++)
{
if (a[aidx - 1] == b[bidx - 1])
cost_ratio = 0;
else
cost_ratio = 1;
calculations[DELETION] = rows[aidx - 1, bidx] + COST_OF_DELETION;
calculations[INSERTION] = rows[aidx, bidx - 1] + COST_OF_INSERTION;
calculations[SUBSTITUTION] = rows[aidx - 1, bidx - 1] + cost_ratio * COST_OF_SUBSTITUTION;
calculations[TRANSPOSITION] = int.MaxValue;
if (aidx > 1 && bidx > 1 && a[aidx] == b[bidx - 1] && a[aidx - 1] == b[bidx])
calculations[TRANSPOSITION] = rows[aidx - 2, bidx - 2] + cost_ratio * COST_OF_TRANSPOSITION;
rows[aidx, bidx] = calculations.Min();
}
}
int score = rows[rows.GetUpperBound(0) - 1, rows.GetUpperBound(1) - 1];
if (a.Contains(b) || b.Contains(a))
score = score / 2;
return score;
}
}
My implementation is based off the algorithm given in the Wikipedia page on Damerau-Levenshtein-Distance
+1 to Lou Franco. But beside that, it seems like you have lots of index issues (note that all 4 for cycles in wiki sample are inclusive, and when 1 is subtracted from aidx/bidx you actually need to subtract 2 because in wiki sample indexes in strings start at 1). My version:
public static int Compute_DamerauLevenshtein_Distance2(string a, string b)
{
int[,] rows = new int[a.Length + 1, b.Length + 1];
int cost_ratio;
int[] calculations = new int[4];
for(int i = 0; i <= rows.GetUpperBound(0); i++)
rows[i, 0] = i;
for(int i = 1; i <= rows.GetUpperBound(1); i++)
rows[0, i] = i;
for(int aidx = 1; aidx <= rows.GetUpperBound(0); aidx++)
{
for(int bidx = 1; bidx <= rows.GetUpperBound(1); bidx++)
{
if(a[aidx - 1] == b[bidx - 1])
cost_ratio = 0;
else
cost_ratio = 1;
calculations[DELETION] = rows[aidx - 1, bidx] + COST_OF_DELETION;
calculations[INSERTION] = rows[aidx, bidx - 1] + COST_OF_INSERTION;
calculations[SUBSTITUTION] = rows[aidx - 1, bidx - 1] + cost_ratio * COST_OF_SUBSTITUTION;
calculations[TRANSPOSITION] = int.MaxValue;
if(aidx > 1 && bidx > 1 && a[aidx - 1] == b[bidx - 2] && a[aidx - 2] == b[bidx - 1])
calculations[TRANSPOSITION] = rows[aidx - 2, bidx - 2] + cost_ratio * COST_OF_TRANSPOSITION;
rows[aidx, bidx] = calculations.Min();
}
}
int score = rows[rows.GetUpperBound(0), rows.GetUpperBound(1)];
return score;
}
This isn't in the Wikipedia article:
if (a.Contains(b) || b.Contains(a))
score = score / 2;
Since it's true for your example -- and integer division of 1/2 == 0, then that could be it.

Categories