I have been practising C# by creating some code to find the factorial of a number.
The problem I have is how C# uses the for loop, and how it keeps the value in a recursive fashion.
Here is my code (Which uses iteration to achieve its goal):
static int Factorial_It(int fac)
{
int fac_test = fac;
for (int i = 1; i <= (fac_test - 1); i++)
{
Console.WriteLine("i = " + i);
Console.Write($"{i} * {fac} = ");
fac = fac * i;
Console.Write(fac + "\n");
}
return fac;
}
I have had to assign a variable for the function's input (fac_test), then use that variable to start the loop as it stays the same throughout.
In a different programming language, I do no need to make this change as the original value inputted is used by the for-loop, and never changed as the loop goes on.
The code works fine with this change, but I would appreciate more knowledge on why C# syntax is like this - Is there a way the for loop doesn't update the value every "loop" ?
For reference, here is the code before I made the fix:
static int Factorial_It(int fac)
{
for (int i = 1; i <= (fac - 1); i++)
{
Console.WriteLine("i = " + i);
Console.Write($"{i} * {fac} = ");
fac = fac * i;
Console.Write(fac + "\n");
}
return fac;
}
As such, for value bigger than 3 or so, the for loop will keep going up until it hits a massive number, because the fac variable is constantly getting bigger (rather than staying the same as the original function input)
I hope my explanation is clear, and sorry for my poor english.
Forp
edit:
Here is the code I am basing this off of, in visual basic.
Function Factorial_It(Fac)
For i = 1 To Fac - 1
Fac = Fac * i
Next i
Return Fac
End Function
Apologies for the confusion.
If you need to loop without the end value moving on you, you could always go backwards.
for (int i = fac - 1; i>0; i--)
{
fac = fac * i;
}
This works because the initializing condition is executed only once at the beginning of the loop. The boundary check is done every time, and no, there is no way to change that behavior, other than using a separate variable.
Related
I have a 2-D array (with dimensions magnitudes n by 5), which I'm picturing in my head like this (each box is an element of the array):
(http://tr1.cbsistatic.com/hub/i/2015/05/07/b1ff8c33-f492-11e4-940f-14feb5cc3d2a/12039.jpg)
In this image, n is 3. I.e, n is the number of columns, 5 is the number of rows in my array.
I want to find an efficient way to iterate (i.e walk) through every path that leads from any cell in the left most column, to any cell in right most column, choosing one cell from every column in between.
It cannot be simply solved by n nested loops, because n is only determined at run time.
I think this means recursion is likely the best way forward, but can't picture how to begin theoretically.
Can you offer some advice as to how to cycle through every path. It seems simple enough and I can't tell what I'm doing wrong. Even just a theoretical explanation without any code will be very much appreciated.
I'm coding in C#, Visual Studio in case that helps.
UPDATE:: resolved using code below from http://www.introprogramming.info/english-intro-csharp-book/read-online/chapter-10-recursion/#_Toc362296468
static void NestedLoops(int currentLoop)
{
if (currentLoop == numberOfLoops)
{
return;
}
for (int counter=1; counter<=numberOfIterations; counter++)
{
loops[currentLoop] = counter;
NestedLoops(currentLoop + 1);
}
}
This is a factorial problem and so you might run quite quickly into memory or value limits issues.
Took some code from this SO post by Diego.
class Program
{
static void Main(string[] args)
{
int n = 5;
int r = 5;
var combinations = Math.Pow(r, n);
var list = new List<string>();
for (Int64 i = 1; i < combinations; i++)
{
var s = LongToBase(i);
var fill = n - s.Length;
list.Add(new String('0', fill) + s);
}
// list contains all your paths now
Console.ReadKey();
}
private static readonly char[] BaseChars = "01234".ToCharArray();
public static string LongToBase(long value)
{
long targetBase = BaseChars.Length;
char[] buffer = new char[Math.Max((int)Math.Ceiling(Math.Log(value + 1, targetBase)), 1)];
var i = (long)buffer.Length;
do
{
buffer[--i] = BaseChars[value % targetBase];
value = value / targetBase;
}
while (value > 0);
return new string(buffer);
}
}
list will contain a list of numbers expressed in base 5 which can be used to found out the path. for example "00123" means first cell, then first cell then second cell, then third cell and finall fourth cell.
Resolved:: see the code posted in the edited question above, and the link to a recursion tutorial, where it takes you through using recursion to simulate N nested, iterative loops.
I'm making a piece of code that takes the fibonacci sequence below 4 000 000 and sums up the even numbers. in order to do this I made an easy piece of code that should work but the "C" variable goes over the 4 000 000 where it shouldn't (it ends on the number:"5 702 887"), as you can see here:
int amount = 4000000;
int A = 1;
int B = 2;
int C = 0;
int answer = 0;
while (C < amount)
{
C = A + B;
if (C % 2 == 0)
{
answer = answer + C;
}
A = B;
B = C;
}
You're modifying C after you check its value. The operator is working as expected.
Your while condition is being evaluated when C = 3524578, then you're incrementing it to the >5,000,000 number, using it, and checking again.
Remember that while loops will always exit when the condition is false.
You should probably adjust the order of your tests. For instance,
int amount = 4000000;
int A = 1;
int B = 2;
int C = 3; // I've changed this to give an appropriate start value
int answer = 0;
while (C < amount)
{
if (C % 2 == 0)
{
answer = answer + C;
}
A = B;
B = C;
C = A + B; // I've moved this so that answer is not in between the altering of this value and the check for it.
}
You could also implement a for loop, which will perform this action in a bit more language-native way.
int amount = 4000000;
int A = 1;
int B = 2;
int answer = 0;
for (int C = 3; C < amount; C = A + B)
{
if (C % 2 == 0)
{
answer = answer + C;
}
A = B;
B = C;
}
The difference here is that the predicate expression is evaluated every time C is set.
I'm in an analogy mood, and I don't think I really explained the actual bug here as much as I just gave the proper code to resolve the issue (teach a man to fish, as they say), so here's a real world example of a flaw in logic like this.
Let's say you're eating orange slices and you absolutely hate seeds and want nothing to do with any oranges that contain them. Regularly, you'd pick one up, check it for seeds, and eat it if it's clear. If you come across one with seeds in it, then gross, and throw away all your remaining orange slices. In pseudo-code, while (the next one doesn't have any seeds) { eat it and grab another. }. Simple enough, right?
However, the way you've written your while loop here, you'd be eating a slice, finding seeds in your mouth, then throwing them away. And as you can see, these are very different situations.
This latter one houses folds of regret because you checked the slice (the variable) after eating (using) it, rather than before. You know not to eat any more, sure, but you've already eaten a seed. You would have been much better off to check it before you ate it, since then you'd have known it was contaminated before it came anywhere near your mouth.
I suspect that you have a false belief common to beginners. The while statement does not terminate the loop immediately the moment that the condition is violated.
The correct way to think about a while loop is that
while(condition)
statement
is logically the same thing as:
continue_label:
if (!condition) goto break_label;
statement
goto continue_label;
break_label:
The condition of a while loop is executed only while entering the loop each time. If you look at your code, C is assigned after this check. Try printing C just before your C = ... assignment - you will see that it does not go beyond the limit.
The next assignment exceeds the value, but the while loop is not entered again.
When C is checked its still bellow 4000000 but then inside the iteration it gets raised above the limit(C = A + B) and in the next iteration its above that value and the loop exits.Instead try this "very dirty" implementation:
int amount = 4000000;
int A = 1;
int B = 2;
int C = 0;
int answer = 0;
for (int i = 0; i < amount; i = A + B)
{
C = A + B;
if (C % 2 == 0)
{
answer = answer + C;
}
A = B;
B = C;
}
So i get this error at the textbox assignation but i don't understand why, can anyone give me an advice on what to do?
private void button2_Click(object sender, EventArgs e)
{
int n = Convert.ToInt32(textBox16.Text);
int t = Convert.ToInt32(textBox17.Text);
matrix.CalculeazaQR(n, t);
string temp;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
temp = matrix.q[i, j].ToString("0.00");
if (j % (n - 1) == 0)
temp += "\n";
temp += ",";
}
}
textBox3.Text = temp;
}
You are assigning temp inside the for loop and compiler can't determine whether you will get inside the loop or not. You may initialize the temp on top like:
string temp = string.Empty;
Statements inside the loop would only execute if the condition is true and the compiler at compile time can't determine whether the condition will be true or not, it will consider the temp to remain unassigned, hence the error.
put like this:
string temp="";
you have to assign string(or any variable) to empty or something before you actually use it.
"can anyone give me an advice on what to do?"
Well, Initialize text:
string temp = string.Empty;
The compiler has no way of knowing if temp (which is used on textBox3.Text = temp;) has a value after the loops (for instance, when n < 1).
For one thing, your loop is broken to start with - only the very last iteration will matter (i.e. when both i and j are n - 1) as you're replacing the value of temp completely.
But the compiler doesn't know that n is positive - it doesn't know that you'll ever get into the loop. In general, the compiler will never assume that you enter the body of an if statement, a for statement, a while statement or a foreach loop - so any assignments made within those bodies don't affect whether a local variable is definitely assigned or not at the end of the statement... and a local variable has to be definitely assigned before you can read from it (as you're doing at the end of the method).
I suspect you actually want a StringBuilder which you append to within the loop:
StringBuilder builder = new StringBuilder();
for (...)
{
for (...)
{
builder.AppendFormat("{0:0.00},", matrix.q[i, j]);
}
builder.Append("\n");
}
textBox3.Test = builder.ToString();
main()
{
....
i = index;
while (i < j)
{
if (ip[i] == "/")
{
ip[i - 1] = (double.Parse(ip[i - 1]) / double.Parse(ip[i + 1])).ToString();
for (int k = i; k < (ip.Length - 2); k++)
{
ip[k] = ip[k + 2];
}
Array.Resize(ref ip, ip.Length - 2);
j = j - 2;
i--;
}
i++;
}
}
For the above code I wanted to apply Oop's concepts.
This pattern repeats almost 5 times (for div,mul,add,sub,pow) in main program, with four identical lines .
To decrease the no of lines and there by to increase efficiency of code, I wrote the same like this.
i = index;
while (i < j)
{
if (ip[i] == "/")
{
ip[i - 1] = (double.Parse(ip[i - 1]) / double.Parse(ip[i + 1])).ToString();
ext.Resize(ip, i, j);
}
i++;
}
class ext
{
public static void Resize(string [] ip, int i, int j)
{
for (int k = i; k < (ip.Length - 2); k++) { ip[k] = ip[k + 2]; }
Array.Resize(ref ip, ip.Length - 2);
j=j-2; i--;
return ;
}
}
Code got compiled successfully. But the problem is the changes in array and variables that took place in called function are not reflecting in main program. The array and variables are remaining unchanged in main program.
I am unable to understand where I went wrong.
Plz guide me.
Thank You.
I don't think you understand what ref parameters are for - once you understand those (and the fact that arrays themselves can't change in size), you'll see why Array.Resize takes a ref parameter. Have a look at my parameter passing article for details.
You can fix your code by changing it like this:
public static void Resize(ref string [] ip, ref int i)
{
for (int k = i; k < (ip.Length - 2); k++)
{
ip[k] = ip[k + 2];
}
Array.Resize(ref ip, ip.Length - 2);
j = j - 2;
i--;
}
and calling it like this:
ext.Resize(ref ip, ref i);
However, I suspect that using a more appropriate data structure would make your code clearer. Is there any reason you can't use a List<string> instead?
You're removing items from the middle of a sequence, so shrinking its length. So using arrays is just making it difficult.
If ip was a List<string> instead of string[]:
i = index;
while (i < j)
{
if (ip[i] == "/")
{
ip[i - 1] = (double.Parse(ip[i - 1]) / double.Parse(ip[i + 1])).ToString();
ip.RemoveAt(i);
ip.RemoveAt(i);
j = j - 2;
i--;
}
i++;
}
It looks like you're parsing an arithmetic expression. However, you might want to allow for parentheses to control the order of evaluation, and that's going to be tricky with this structure.
Update: What your code says is: You are going to scan through a sequence of strings. Anywhere in that sequence you may find a division operator symbol: /. If so, you assume that the things on either side of it can be parsed with double.Parse. But:
( 5 + 4 ) / ( 6 - 2 )
The tokens on either side of the / in this example are ) and ( so double.Parse isn't going to work.
So I'm really just checking that you have another layer of logic outside this that deals with parentheses. For example, perhaps you are using recursive descent first, and then only running the piece of code you posted on sequences that contain no parentheses.
If you want the whole thing to be more "objecty", you could treat the problem as one of turning a sequence of tokens into a tree. Each node in the tree can be evaluated. The root node's value is the value of the whole expression. A number is a really simple node that evaluates to the number value itself. An operator has two child nodes. Parenthesis groups would just disappear from the tree - they are used to guide how you build it. If I have some time later I could develop this into a short example.
And another question: how are you splitting the whole string into tokens?
I need to resample big sets of data (few hundred spectra, each containing few thousand points) using simple linear interpolation.
I have created interpolation method in C# but it seems to be really slow for huge datasets.
How can I improve the performance of this code?
public static List<double> interpolate(IList<double> xItems, IList<double> yItems, IList<double> breaks)
{
double[] interpolated = new double[breaks.Count];
int id = 1;
int x = 0;
while(breaks[x] < xItems[0])
{
interpolated[x] = yItems[0];
x++;
}
double p, w;
// left border case - uphold the value
for (int i = x; i < breaks.Count; i++)
{
while (breaks[i] > xItems[id])
{
id++;
if (id > xItems.Count - 1)
{
id = xItems.Count - 1;
break;
}
}
System.Diagnostics.Debug.WriteLine(string.Format("i: {0}, id {1}", i, id));
if (id <= xItems.Count - 1)
{
if (id == xItems.Count - 1 && breaks[i] > xItems[id])
{
interpolated[i] = yItems[yItems.Count - 1];
}
else
{
w = xItems[id] - xItems[id - 1];
p = (breaks[i] - xItems[id - 1]) / w;
interpolated[i] = yItems[id - 1] + p * (yItems[id] - yItems[id - 1]);
}
}
else // right border case - uphold the value
{
interpolated[i] = yItems[yItems.Count - 1];
}
}
return interpolated.ToList();
}
Edit
Thanks, guys, for all your responses. What I wanted to achieve, when I wrote this questions, were some general ideas where I could find some areas to improve the performance. I haven't expected any ready solutions, only some ideas. And you gave me what I wanted, thanks!
Before writing this question I thought about rewriting this code in C++ but after reading comments to Will's asnwer it seems that the gain can be less than I expected.
Also, the code is so simple, that there are no mighty code-tricks to use here. Thanks to Petar for his attempt to optimize the code
It seems that all reduces the problem to finding good profiler and checking every line and soubroutine and trying to optimize that.
Thank you again for all responses and taking your part in this discussion!
public static List<double> Interpolate(IList<double> xItems, IList<double> yItems, IList<double> breaks)
{
var a = xItems.ToArray();
var b = yItems.ToArray();
var aLimit = a.Length - 1;
var bLimit = b.Length - 1;
var interpolated = new double[breaks.Count];
var total = 0;
var initialValue = a[0];
while (breaks[total] < initialValue)
{
total++;
}
Array.Copy(b, 0, interpolated, 0, total);
int id = 1;
for (int i = total; i < breaks.Count; i++)
{
var breakValue = breaks[i];
while (breakValue > a[id])
{
id++;
if (id > aLimit)
{
id = aLimit;
break;
}
}
double value = b[bLimit];
if (id <= aLimit)
{
var currentValue = a[id];
var previousValue = a[id - 1];
if (id != aLimit || breakValue <= currentValue)
{
var w = currentValue - previousValue;
var p = (breakValue - previousValue) / w;
value = b[id - 1] + p * (b[id] - b[id - 1]);
}
}
interpolated[i] = value;
}
return interpolated.ToList();
}
I've cached some (const) values and used Array.Copy, but I think these are micro optimization that are already made by the compiler in Release mode. However You can try this version and see if it will beat the original version of the code.
Instead of
interpolated.ToList()
which copies the whole array, you compute the interpolated values directly in the final list (or return that array instead). Especially if the array/List is big enough to qualify for the large object heap.
Unlike the ordinary heap, the LOH is not compacted by the GC, which means that short lived large objects are far more harmful than small ones.
Then again: 7000 doubles are approx. 56'000 bytes which is below the large object threshold of 85'000 bytes (1).
Looks to me you've created an O(n^2) algorithm. You are searching for the interval, that's O(n), then probably apply it n times. You'll get a quick and cheap speed-up by taking advantage of the fact that the items are already ordered in the list. Use BinarySearch(), that's O(log(n)).
If still necessary, you should be able to do something speedier with the outer loop, what ever interval you found previously should make it easier to find the next one. But that code isn't in your snippet.
I'd say profile the code and see where it spends its time, then you have somewhere to focus on.
ANTS is popular, but Equatec is free I think.
few suggestions,
as others suggested, use profiler to understand better where time is used.
the loop
while (breaks[x] < xItems[0])
could cause exception if x grows bigger than number of items in "breaks" list. You should use something like
while (x < breaks.Count && breaks[x] < xItems[0])
But you might not need that loop at all. Why treat the first item as special case, just start with id=0 and handle the first point in for(i) loop. I understand that id might start from 0 in this case, and [id-1] would be negative index, but see if you can do something there.
If you want to optimize for speed then you sacrifice memory size, and vice versa. You cannot usually have both, except if you make really clever algorithm. In this case, it would mean to calculate as much as you can outside loops, store those values in variables (extra memory) and use them later. For example, instead of always saying:
id = xItems.Count - 1;
You could say:
int lastXItemsIndex = xItems.Count-1;
...
id = lastXItemsIndex;
This is the same suggestion as Petar Petrov did with aLimit, bLimit....
next point, your loop (or the one Petar Petrov suggested):
while (breaks[i] > xItems[id])
{
id++;
if (id > xItems.Count - 1)
{
id = xItems.Count - 1;
break;
}
}
could probably be reduced to:
double currentBreak = breaks[i];
while (id <= lastXIndex && currentBreak > xItems[id]) id++;
and the last point I would add is to check if there is some property in your samples that is special for your problem. For example if xItems represent time, and you are sampling in regular intervals, then
w = xItems[id] - xItems[id - 1];
is constant, and you do not have to calculate it every time in the loop.
This is probably not often the case, but maybe your problem has some other property which you could use to improve performance.
Another idea is this: maybe you do not need double precision, "float" is probably faster because it is smaller.
Good luck
System.Diagnostics.Debug.WriteLine(string.Format("i: {0}, id {1}", i, id));
I hope it's release build without DEBUG defined?
Otherwise, it might depend on what exactly are those IList parameters. May be useful to store Count value instead of accessing property every time.
This is the kind of problem where you need to move over to native code.