Call method with new parameter values for each loop in C# - c#

[HttpPost]
public ActionResult ShowDetailRate(FormCollection form)
{
List<Calculation> finalList = new List<Calculation>();
Calculation calc3 = new Calculation();
double InterestRate = 0;
double guess = 0.01;
double guess2 = 0.03;
for (int i = 0; i < 50; i++)
{
InterestRate = secantInterestRate(guess, guess2, form);
if (radio == "inArrears")
{
radioCalc = 0;
}
else
{
radioCalc = InvoiceAmount;
}
calc3.PeriodStartDate = PeriodStartDate;
calc3.PeriodEndDate = PeriodEndDate;
if (DTC == "365/365")
{
calc3.NumberOfDays = Convert.ToInt32((calc3.PeriodEndDate - calc3.PeriodStartDate).Days) + 1;
}
else if (DTC == "360/360")
{
calc3.NumberOfDays = 30;
}
calc3.InvoiceAmount = InvoiceAmount;
calc3.InterestRate = InterestRate;
calc3.InterestAmount = (PV - radioCalc) * InterestRate / DTCyear * calc3.NumberOfDays;
calc3.Amortization = (calc3.InvoiceAmount - calc3.InterestAmount);
calc3.PresentValue = PV - calc3.Amortization;
calc3.StartValue = PV;
finalList.Add(calc3);
var count = finalList.Count();
if (finalList[count].PresentValue != FV)
{
guess = guess2;
guess2 = calc3.InterestRate;
continue;
}
else
break;
}
return PartialView("ShowDetail", finalList);
}
In my method above I'm using my variable InterestRate to call a method called secantInterestRate with 3 parameters (double, double, FormCollection). The first round for the loop I want the first 2 parameters to be set as they are (0.01, 0.03), but in the second loop-round I want guess = guess 2, and guess2 = calc3.InterestRate. And still be calling the method secantInterestRate in the beginning of the loop but with the new values. I have tried with a small if in the end:
var count = finalList.Count() - 3;
if (finalList[count].PresentValue != FV)
{
guess = guess2;
guess2 = calc3.InterestRate;
continue;
}
else
break;
But this don't work because when the loop starts over guess will be 0.01 and guess2 will be 0.03 again, and not like I want it.
Is it possible to make guess = guess2 and guess2 = calc3.InterestRate for every new round in the loop?

something like this?
if (i==0) {
guess = guess2;
guess2 = calc3.InterestRate;
} else {
// you don't want to change the values after the first time through; do nothing
}
PS: I suggest you factor out the calculation code from the form-processing code, or in some other way make the method more readable. Currently it's really hard to see the logic as there's so many lines of code, and that's probably the main reason it's hard to solve any small problems like this one.

Change your code according to the following:
....
for (int i = 0; i < 50; i++)
{
if (i > 0)
{
guess = guess2;
guess2 = calc3.InterestRate;
}
InterestRate = secantInterestRate(guess, guess2, form);
...

Related

My partial array keeps adding the empty data C#

I'm new to C# and we need to create an array that can hold 100 scores. But it needs to also accept something smaller (txt file with numbers between 0-100). My issue is that even tho I add a txt file that has 50 scores, it will think there is another 50 'blank scores' and it will count those as 0. So when my code does the average, total, and lowest score, it will mess it up. My textbook isn't being very help with the answer.
private double Total(double[] iArray)
{
double total = 0;
total = iArray.Length;
return total;
}
//Average test score
private double Average(double[] iArray)
{
double total = 0;
double average;
for (int index = 0; index < iArray.Length; index++)
{
total += iArray[index];//look into later
}
average = (double)total / iArray.Length;
return average;
} //done
//for hightest test score
private double Highest(double[] iArray)
{
double highest = iArray[0];
for (int index = 1; index < iArray.Length; index++)
{
if (iArray[index] > highest)
{
highest = iArray[index];
}
}
return highest;
} //done
private double Lowest(double[] iArray)
{
double lowest = iArray[0];
for (int index = 1; index < iArray.Length; index++)
{
if (iArray[index] < lowest)
{
lowest = iArray[index];
}
}
return lowest;
}//done
private void addFileButton_Click(object sender, EventArgs e)
{
try
{
const int SIZE = 100; //number of test
double[] scores = new Double[SIZE]; //array of the test scores
int index = 0; //loop counter
int count = 0;
double highestScore;
double lowestScore;
double averageScore;
double totalScore;
//Asking user to open a file
StreamReader inputFile;
if (openFile.ShowDialog() == DialogResult.OK)
{
inputFile = File.OpenText(openFile.FileName);
while (!inputFile.EndOfStream && count < scores.Length)//switching index to count
{
scores[count] = int.Parse(inputFile.ReadLine());
count++;
}
inputFile.Close();
}
else
{
MessageBox.Show("Operation Canceled.");
}
//Display test scores
for (index = 0; index < count; index++)
{
scoreListBox.Items.Add(scores[index].ToString());
}
//grabbing information
highestScore = Highest(scores);
lowestScore = Lowest(scores);
averageScore = Average(scores);
totalScore = Total(scores);
//display values
highesScoreLabel.Text = highestScore.ToString();
lowestScoreLabel.Text = lowestScore.ToString();
averageTestScoreLabel.Text = averageScore.ToString();
totalTestScoresLabel.Text = totalScore.ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
You might just have to use Array.Resize then:
while (!inputFile.EndOfStream && scores.Count <= SIZE)
{
scores[count] = int.Parse(inputFile.ReadLine());
count++;
}
Array.Resize(scores, --count);
See if that works.
This was suggested before the OP's comment clarifying the should specifically use an array:
What if you used a List<double> when collecting the scores, then .ToArray() before you pass it into your other methods?
const int SIZE = 100;
List<double> scores = new List<double>();
[...]
if (openFile.ShowDialog() == DialogResult.OK)
{
inputFile = File.OpenText(openFile.FileName);
while (!inputFile.EndOfStream && scores.Count <= SIZE)
{
scores.Add(int.Parse(inputFile.ReadLine()));
count++;
}
[...]
var arrScores = scores.ToArray();
//grabbing information
highestScore = Highest(arrScores);
lowestScore = Lowest(arrScores);
averageScore = Average(arrScores);
totalScore = Total(arrScores);
Notice that the while loop has the condition changed for scores.Count <= SIZE to still only allow up to 100 scores.
Instead of constructing the Array yourself and implementing all these methods, I suggest, you read up in LINQ. LINQ stands for Language INtegrated Query and is essentially a bunch of extension methods on IEnumerable<T> that provide all of the functionality you need here.
I rewrote your event handler to use LINQ and it became much simpler.
private void addFileButton_Click(object sender, EventArgs e)
{
try
{
// Easier to follow if we just exit early
if (openFile.ShowDialog() != DialogResult.OK)
{
MessageBox.Show("Operation Canceled.");
return;
}
var scores = File.ReadAllLines(openFile.FileName)
// Always use TryParse to avoid exceptions
.Select(l => int.TryParse(l, out var score) ? score : -1)
// Filter out everything that is no valid score
.Where(s => s >= 0)
// You could also use ToList() here for a possible minimal performance gain and the possibility to add items later.
.ToArray();
// Display test scores
// We are using foreach instead of for here because we do not care about indexes. We simply want to add each item.
// We also do not need to add the ToString(), just adding an int is fine.
foreach (var score in scores)
scoreListBox.Items.Add(score);
// grabbing information
// We use LINQ methods here. Microsoft was nice enough di implement a bunch of often used methods on collections for us.
var highestScore = scores.Max();
var lowestScore = scores.Min();
var averageScore = scores.Average();
var totalScore = scores.Sum();
//display values
highesScoreLabel.Text = highestScore.ToString();
lowestScoreLabel.Text = lowestScore.ToString();
averageTestScoreLabel.Text = averageScore.ToString();
totalTestScoresLabel.Text = totalScore.ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

Is there a way of comparing 2 variables in a grid like way instead of nested if statements?

I am dealing with a prisoners paradox type problem where there are multiple combinations (2x2 -> 4) and each has a different result. Is there a good way of looking at the inputs and deciding the output other than nested if statements which can get confusing if theres more than 2 options for inputs.
For example there are 2 prisoners being questioned: A and B. If both choose to expose the other then they both are imprisoned for 5 years, if both stay loyal then they both only recieve 1 year in prison, however if A exposes B but B remains loyal, A will be set free and B will be imprisoned for 10 years.
Currently my logic looks roughly like this:
if (A.Cooperate)
{
if (B.Cooperate)
{
A.Sentence = 5;
B.Sentence = 5;
}
else
{
A.Sentence = 0;
B.Sentence = 10;
}
}
else
{
if (B.Cooperate)
{
A.Sentence = 10;
B.Sentence = 0;
}
else
{
A.Sentence = 1;
B.Sentence = 1;
}
}
Although I would like to add more options than just a boolean yes/no and fear it will become over complicated with many nested if statements.
This is how I would do it to improve readability and logic
static void Interrogate(Prisoner A, Prisoner B)
{
if (!B.Cooperate && !A.Cooperate)
{
A.Sentence = 1;
B.Sentence = 1;
}
else if (B.Cooperate && !A.Cooperate)
{
A.Sentence = 10;
B.Sentence = 0;
}
else if (A.Cooperate && !B.Cooperate)
{
A.Sentence = 0;
B.Sentence = 10;
}
else
{
A.Sentence = 5;
B.Sentence = 5;
}
}
You can use the new switch format
switch (A.Cooperate, B.Cooperate) {
case (true, false): {
.....
}
break;
case (true, true): {
....
}
}

How to get values inside while loop and put it outside c# winform Crystal report

I've been searching this page and other pages in this matter. I know it's not possible to get the data inside the while loop with direct assigning of variables, so I've tried to put it to label before and it works but only to the first value of the finalcred and finaldeb. It will not reset to fetch another value, so my real question is; Is there any other way to get the value inside the while loop and use it outside?
I have tried to declare it outside while and assign default value and the result will always be the default. It will not change.
r = t.NewRow();
//somecode..all good here
while (counterdate <= monthval)
{
//allgood in this part
totalcred = 0;
totaldeb = 0;
balance = 0;
crednum = 0;
debnum = 0;
if (readgetcode1.HasRows)
{
while (readgetcode1.Read())
{
readgetcred.Read();
readgetdeb.Read();
if (readgetdeb.HasRows)
{
debnum = Convert.ToDecimal(readgetdeb.GetValue(0));
}
else
{
debnum = 0;
}
if (readgetcred.HasRows)
{
crednum = Convert.ToDecimal(readgetcred.GetValue(0));
}
else
{
crednum = 0;
}
totalcred += crednum;
totaldeb += debnum;
if (strType == "Debit")
{
balance = totaldeb - totalcred;
}
else
{
balance = totalcred - totaldeb;
}
allbal += balance;
}
}
else
{
allbal = 0;
}
if (readprevCred.HasRows)
{
prevBalNum = Convert.ToDecimal(readprevBal.GetValue(0));
}
else
{
prevBalNum = 0;
}
if (strType == "Debit")
{
finaldeb = prevBalNum + allbal;
finalcred = 0;
}
else
{
finalcred = prevBalNum + allbal;
finaldeb = 0;
}
counterdate++;
}//while counterdate looping
r["accntCode"] = codevalue;
r["accntName"] = accntnameval;
r["DebitAmount"] = finaldeb;//this is the problem
r["CreditAmount"] = finalcred;;//this is the problem
t.Rows.Add(r);
//while readcodecheck in counter for code

Mixed managed C++ method does not always return the same result to the calling C# code

A C++ method returns the correct value when I use a conditional breakpoint, but an incorrect value without a breakpoint.
C# method which calls C++:
bool SetProperty(Element element, Node referencePoint, List<Materializer> materializers, List<ulong> properties)
{
// Loop over STLs
for (int i = 0; i < materializers.Count; i++)
{
Materializer materializer = materializers[i];
if (materializer.IsPointInside(referencePoint.X, referencePoint.Y, referencePoint.Z, pentalTreeDatasets[i].top))
{
element.PropertyId = properties[i];
return true;
};
}
return false;
}
C++ methods in the header file:
int CountIntersects(double x, double y, double z, PentalTreeNode ^root)
{
Math3d::M3d rayPoints[2], intersectionPoint;
rayPoints[0].set(x,y,z);
rayPoints[1].set(x,y,1.0e6);
if(!root)
return 0;
else
{
int special = CountIntersects(x,y,z,root->special);
if (x <= root->xMax && x >= root->xMin && y <= root->yMax && y >= root->yMin)
{
if( _stlMesh->IsRayIntersectsPoly(root->index, rayPoints, intersectionPoint))
{
return (1 + special);
}
else
return special;
}
else
{
if (y>root->yMax)
{
return (CountIntersects(x,y,z,root->top)+special);
}
else if(y<root->yMin)
{
return (CountIntersects(x,y,z,root->bottom)+special);
}
else if(x<root->xMin)
{
return (CountIntersects(x,y,z,root->left)+special);
}
else if(x>root->xMax)
{
return (CountIntersects(x,y,z,root->right)+special);
}
else
return special;
}
}
}
bool IsPointInside(double x, double y, double z, PentalTreeNode ^root)
{
int intersectionCount = 0;
Math3d::M3d rayPoints[2], intersectionPoint;
rayPoints[0].set(x,y,z);
rayPoints[1].set(x,y,1.0e6);
if(_box->IsContainingPoint(x,y,z))
{
intersectionCount=CountIntersects(x,y,z,root);
return (intersectionCount%2!=0);
}
}
C++ methods in other header files:
bool IsRayIntersectsPoly(int nPolygonIndex, Math3d::M3d RayPoints[2], CVector3D& IntersectionPoint)
{
CMeshPolygonBase& Poly = m_PolygonArray[nPolygonIndex];
CArrayResultI Result;
int* pPolygonPoints = GetPolygonPoints(Poly, Result);
Math3d::MPlane TrianglePlane;
double Atmp[3], A;
CVector3D* pPoints[3];
pPoints[0] = &m_PointArray[*pPolygonPoints].m_Position;
for(int i = 1; i < Result.GetSize() - 1; i++)
{
pPoints[1] = &m_PointArray[*(pPolygonPoints+i)].m_Position;
pPoints[2] = &m_PointArray[*(pPolygonPoints+i+1)].m_Position;
TrianglePlane.Init(*pPoints[0], *pPoints[1], *pPoints[2]);
TrianglePlane.IntersectLine(RayPoints[0], RayPoints[1], IntersectionPoint);
A = GetTriangleArea(*pPoints[0], *pPoints[1], *pPoints[2]);
for(int j = 0; j < 3; j++)
{
Atmp[j] = GetTriangleArea(*pPoints[j], *pPoints[(j+1)%3], IntersectionPoint);
}
if( fabs(A - Atmp[0] - Atmp[1] - Atmp[2]) < 1.0e-5 ) return true;
}
return false;
};
double GetTriangleArea(CVector3D& T1, CVector3D& T2, CVector3D& T3)
{
double a, b, c, s;
a = (T1 - T2).length();
b = (T2 - T3).length();
c = (T3 - T1).length();
s = 0.5 * (a + b + c);
return( sqrt(s * (s - a)* (s - b)* (s - c)) );
}
When I start the program which calls SetProperty() within the for-loop, the results for some iterator values are wrong. When I set conditional breakpoints for critical iterator values in the for-loop and step over it, then the result is OK for that item. What may be the problem?
This is method in which I post breakpoint. For example, for critical element.Id==2393.
private void StartButton_Click(object sender, EventArgs e)
{
DateTime startTime = DateTime.Now;
List<Materializer> materializers = new List<Materializer>();
List<ulong> properties = new List<ulong>();
// Load STLs
for (int i = 0; (int)i < (this.dataGridView.RowCount - 1); i++)
{
if (dataGridView.Rows[i].Cells[1].Value != null && (string)dataGridView.Rows[i].Cells[1].Value != "")
{
Materializer materializer = new Materializer();
materializer.LoadSTLMesh(dataGridView.Rows[i].Cells[0].Value.ToString());
materializers.Add(materializer);
properties.Add((ulong)dataGridView.Rows[i].Cells[1].Tag);
}
}
CreatePentalTrees(materializers);
int processedElementCount = 0;
int changedElementCount = 0;
// Loop over elements
foreach (Element element in model.ElementsList.Values)
if ((element.Topology == 7 || element.Topology == 8) && !lockedProperties.ContainsKey(element.PropertyId)) // 3D elements only
{
Node center = this.CenterPoint(element, model.NodesList);
if (element.Id == 2393)
{
//if breakpoints thats ok, else not ok
Console.WriteLine(element.Id);
Console.WriteLine(element.PropertyId);
}
if (SetProperty(element, center, materializers, properties)) // Check for center point
{
//changedElements.Add(element.Id, true);
changedElementCount++;
}
else
{
// Check for all nodes if center point does not belong to any STL
int[] nodeOrder;
switch (element.Topology)
{
case 7:
nodeOrder = wedgeNodeOrder;
break;
case 8:
nodeOrder = brickNodeOrder;
break;
default:
throw new Exception("Unknown topology " + element.Topology.ToString());
}
for (int i = 0; i < nodeOrder.Length; i++)
{
Node node = model.NodesList[element.NodeIds[nodeOrder[i]]];
if (SetProperty(element, node, materializers, properties))
{
//changedElements.Add(element.Id, true);
changedElementCount++;
break;
}
}
}
if (++processedElementCount % 100 == 0)
{
labelTime.Text = "Changed/processed elements: " + changedElementCount.ToString() + "/" + processedElementCount.ToString();
labelTime.Refresh();
Application.DoEvents();
}
}
DateTime endTime = DateTime.Now;
labelTime.Text = "Total time: " + (endTime - startTime).TotalSeconds.ToString() + " s";
MessageBox.Show("Completed.");
SaveFileDialog saveFileDlg = new SaveFileDialog();
saveFileDlg.Title = "Save FEMAP neutral file";
saveFileDlg.Filter = "(*.neu)|*.neu";
if (saveFileDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
FemapNeutral.ExportNeu(saveFileDlg.FileName, model);
}
}
You seem to be calling a lot of methods you haven't listed, and/or the wall of code made me get lost. Adding that code won't help: reducing your problem to a simpler one that demonstrates the problem might.
However, the most likely cause of your problem, if you have unmanaged code reading managed data, is that you failed to marshal or pin the data prior to using the managed code.
Unpinned data can be moved around by the garbage collector in unexpected ways.

Autoexpand textbox while typing

I am needing an autoexpanding textbox like facebook has for it's status updates. I have code for it but for some reason it's not fully working correctly. It's updating the textbox and expanding it, but it is doing it way too soon. i am wanting it to expand when it gets to the end of the line. But it is doing it after 20 characters are entered! I have two different methods i have tried, they both do the same thing. Any suggestions on changing my code?
function sz(t) {
var therows = 0
var thetext = document.getElementById(t.id).value;
var newtext = thetext.split("\n");
therows += newtext.length
document.getElementById(t.id).rows = therows;
return false;
}
function sz(t)
{
a = t.value.split('\n');
b = 1;
for (x = 0; x < a.length; x++)
{
if (a[x].length >= t.cols)
{
b += Math.floor(a[x].length / t.cols);
}
}
b += a.length;
if (b > t.rows)
{
t.rows = b;
}
}
Check out this fiddle.
I think your problem was using txtbox.id rather than just passing the id.

Categories

Resources