So. I've been working on a tip calculator for a local business and i'm running into some issues.
Its supposed to first take 10% of the total tips and subtract it from the total tip amount (this is a bonus for people closing the store), take the remaining tip amount and divide it giving front workers 65% and back workers 35% then take the number of front workers who are closing, divide the 10% among the front workers who are closing and the back workers who are closing and give them their respective amounts as mentioned before (65% or 35%) ontop of the split 10% then spit the totals out into their respective boxes.
Its not spitting out the amounts. I've written the equations out several times on paper and implemented them but somehow they are quite clicking.
private void calcButton_Click(object sender, EventArgs e)
{
//define objects
double tipAmount;
double tipReduction;
double tipDeduction;
double frontWorkers;
double backWorkers;
double closeFrontWorkers;
double closeBackWorkers;
double frontWorkersUse;
double backWorkersUse;
double closeFrontWorkersUse;
double closeBackWorkersUse;
double frontPer;
double backPer;
double closeFrontPer;
double closeBackPer;
double tipDeductionPer;
double totalCloseWorkers;
double frontWorkersNew;
double backWorkersNew;
tipAmount = double.Parse(tipBox.Text);
frontWorkers = double.Parse(frontWorkBox.Text);
backWorkers = double.Parse(backWorkBox.Text);
closeFrontWorkers = double.Parse(frontCloseWorkBox.Text);
closeBackWorkers = double.Parse(backCloseWorkBox.Text);
frontWorkersNew = frontWorkers + closeFrontWorkers;
backWorkersNew = backWorkers + closeBackWorkers;
tipReduction = tipAmount * .9;
tipDeduction = tipAmount - tipReduction;
totalCloseWorkers = closeFrontWorkers + closeBackWorkers;
tipDeductionPer = tipDeduction / totalCloseWorkers;
frontWorkersUse = tipReduction * .65;
backWorkersUse = tipReduction * .35;
closeFrontWorkersUse = (frontWorkersUse/frontWorkersNew);
closeBackWorkersUse = (backWorkersUse/backWorkersNew);
frontPer = frontWorkersUse / frontWorkersNew;
backPer = backWorkersUse / backWorkersNew;
closeFrontPer = (closeFrontWorkersUse / closeFrontWorkers) + tipDeduction;
closeBackPer = (closeBackWorkersUse / closeBackWorkers) + tipDeduction;
totalFrontWorkBox.Text = String.Format("{0:c}", frontPer);
totalBackWorkBox.Text = String.Format("{0:c}", backPer);
totalCloseWorkBoxFront.Text = String.Format("{0:c}", closeFrontPer);
totalCloseWorkBoxBack.Text = String.Format("{0:c}", closeBackPer);
}
Well, your (main) issue is in the logic.
I copied your code into Linqpad and changed it so that it wasn't relying on text boxes. Then I put some simple values in place of your numbers, and compared to what I'd expect. This showed that your error was with the closing workers' tip calculations, rather than the general tips. And the closing workers' tips were too big!
I then had a look at the relevant bits of your code and wondered why you were assigning the variable tipDeductionPer but never using its value - you're using tipDeduction and giving each of the closing staff the full amount!
What everyone else says in the comments is valid too. Your code could be a lot cleaner and easier to understand, and you'd find it easier to spot bugs. You could post on Code Review once you've fixed your bugs to get some pointers on how to improve it.
Related
After several searches and mistakes on my part, I finally managed to get out of it and get a result from the MSF solver.
However, it's not perfect, because I still have a difference against me in my C# code.
In the Excel workbook I have 6 solvers, relatively identical.
Only one solver per tab, but I have a lot of calculations.
In order to best stick to the Excel workbook, I created one method per cell containing a formula.
My code works, in the sense that if I give it the same data as Excel I have the same results, but with the solver I have a little difference.
Here's what I did, and I'd like you to tell me if there's anything I can improve by trying to keep my methods (representing my Excel Cells)
Each representation of the cells is created twice.
I need to have the value of my cell to do other calculations and it seems that I can't put methods returning a double, in the solver.
Classic method:
private double Cell_I5()
{
double res = 0;
res = (Math.Exp(-Var.Calc.Var4 * Var.Calc.De * M23) - 1) / (-Var.Calc.Var4 * Var.Calc.De * M23);
return res;
}
Method for the solver:
private Term Solv_I5()
{
Term res = 0;
res = (Model.Exp(-Var.Calc.Var4 * Var.Calc.De * Solver_M23) - 1) / (-Var.Calc.Var4 * Var.Calc.De * Solver_M23);
return res;
}
'M23' is a double
'Solver_M23' is a Decision
'Var4' is a double as well as 'De'.
So I use the return value with "Term" and I change all the Math functions to 'Model', except Math.Pi which is a constant.
You can imagine that there are close to 60 to 70 methods involved like that.
My method for the solver:
public void StartSolver()
{
var solver = SolverContext.GetContext();
solver.ClearModel();
var model = solver.CreateModel();
//Instanciation des variables du Solver en format Real(double) Non Negative
Solver_M22 = new Decision(Domain.RealNonnegative, "M22");
Solver_M23 = new Decision(Domain.RealNonnegative, "M23");
Solver_M24 = new Decision(Domain.RealNonnegative, "M24");
Solver_M25 = new Decision(Domain.RealNonnegative, "M25");
Solver_M26 = new Decision(Domain.RealNonnegative, "M26");
model.AddDecision(Solver_M22);
model.AddDecision(Solver_M23);
model.AddDecision(Solver_M24);
model.AddDecision(Solver_M25);
model.AddDecision(Solver_M26);
model.AddConstraint("M22a", Solver_M22 <= 4);
model.AddConstraint("M22b", Solver_M22 >= 0);
model.AddConstraint("M23a", Solver_M23 <= 2);
model.AddConstraint("M23b", Solver_M23 >= 0.001);
model.AddConstraint("M24a", Solver_M24 <= 2);
model.AddConstraint("M24b", Solver_M24 >= 0);
model.AddConstraint("M25a", Solver_M25 <= 2);
model.AddConstraint("M25b", Solver_M25 >= 0);
model.AddConstraint("M26a", Solver_M26 <= 2);
model.AddConstraint("M26b", Solver_M26 >= 0.001);
//Test with classical calculation methods
double test = Cell_H33() + Cell_H23();
//Adding Solver Methods
model.AddGoal("SommeDesCarresDesEquartsGlobal", GoalKind.Minimize, Solv_H33() + Solv_H23());
// Solve our problem
var solution = solver.Solve();
// Get our decisions
M22 = Solver_M22.ToDouble();
M23 = Solver_M23.ToDouble();
M24 = Solver_M24.ToDouble();
M25 = Solver_M25.ToDouble();
M26 = Solver_M26.ToDouble();
string s = solution.Quality.ToString();
//For test
double testSortie = Cell_H33() + Cell_H23();
}
Questions:
1)
At no time do I indicate whether it is a linear calculation or not. How to indicate if necessary?
In Excel it is declared nonlinear
I saw that the solver was looking for the best method on its own.
2)
Is there something I'm not doing right, because I don't have the same value (with Excel)? I checked several times all the methods by one, with the amount that I missed, maybe, something, I will recheck tomorrow.
3)
Apart from doing the calculation with the classic methods, I have not found a way to find my result. From the 'solution' object
How to extract it from the result if possible?
4)
Here is the result of the 5 variables I find MSF C#:
0.06014756519010750
0.07283670953453890
0.07479568348101340
0.02864805010533950
0.00100000002842722
And what I find the Excel solver:
0.0000
0.0010
0.0141
0.0000
0.0010
Is there a way to restrict the number of decimal places directly in the calculations?
Because when I reduce manually (after calculation) that changes my result quite a bit?
Thank you.
[EDIT] Forgot to post this message it was still pending.
This morning I ran the C# solver calculation again and the result is really different with a huge difference in the result.
I remind you that I want to minimize the result.
Excel = 3.92
C#=8122.34
Result not acceptable at all.
[EDIT 2]
I may have a clue:
When I doing a simple calculation, such as:
private Term Solv_I5()
{
Term res = 0;
res = Model.Exp(-Var.Calc.Var4 * Var.Calc.Den * Solver_M25);
return res;
}
the result is:
{Exp(Times(-4176002161226263/70368744177664, M25))}
Why "Times"
All formulas with multiplication contain Times.
For divisions there is 'Quotient', additions 'Plus', but multiplications 'Times !!!
Question 4)
Am I doing the multiplications wrong in a 'Term'.?
Do you have an idea?
[EDIT 3]
I just saw that "times" was not a stupid term, another misunderstanding on my part of the English language, sorry.
So that doesn't solve my problem.
Can you help me please.
I am attempting to implement a trailing stop loss functionality in C# similar to what is described here:
https://www.multicharts.com/trading-software/index.php/SetPercentTrailing
Basically, if the profit rises over a certain amount and then drops by a certain percentage of that amount, it closes the order.
Unfortunately, for whatever reason, it doesn't seem to be working. It never exits when there's a profit, but the stop-loss works. I am inexperienced with C# and after spending quite a while on this I'm stumped as to what could be going wrong - my thought is that I may be using lists incorrectly. This is being written with QuantConnect/LEAN. Here is what I've written:
// 0.00025m is the conversion factor for profitPercentage into recognizable integers
var profitPercentage = Portfolio[_symbol].UnrealizedProfitPercent / 0.00025m;
var percentages = new List<decimal>();
var profitThreshold = 10;
decimal maxProfit;
decimal trailingPercent = 10;
decimal stopLoss = -10;
if (profitPercentage > profitThreshold)
{
percentages.Add(profitPercentage);
percentages.Sort();
maxProfit = percentages[percentages.Count - 1];
if (profitPercentage < (maxProfit - (maxProfit * trailingPercent)))
{
SetHoldings(_symbol, 0);
percentages.Clear();
position = "none";
}
}
else if (profitPercentage < stopLoss)
{
Console.WriteLine("Profit:" + profitPercentage);
SetHoldings(_symbol, 0);
percentages.Clear();
position = "none";
}
The stop loss seems to work fine, so profitPercentage appears to be outputting the right values. The issue seems to lie in the logic related to the list. Similarly, if I simplify the first if statement thus:
if (profitPercentage > profitThreshold)
{
SetHoldings(_symbol, 0);
}
This also works fine.
I am attempting to write a program that will use a post conditional loop. The loop is calculating Celsius to Fahrenheit conversions. I have the equation down but i cannot get the output that way i need it to be.
I need to output both temperatures to the same label while keeping the C and F temps in their own organized column. here is a link showing exactly what i am attempting to do:
After that, i need to right justify the table while keeping the C temp data in the same place.
I am not sure how to do either of these and apparently after 2 and a half hours of searching on google, it seems google doesnt know either. I am a beginner in C# and i cannot find anything that says how to do this specifically so i can learn to do it myself. Any help will greatly be appreciated. Happy holidays!!!
This is my current code i have, Im still working on it but the data keeps getting bunched together, and i need only to have the words Fahrenheit and Celceius displayed only once at the top
double Celceius=0;
double Fahrenheit;
lblOUT.BackColor=Color.Red;
while (Celceius <= 100)
{
Fahrenheit = 32 + (Celceius * 1.8);
lblOUT.Text += "Celceius"+ "Fahrenheit"+Convert.ToString(Celceius) + Environment.NewLine + Convert.ToString(Fahrenheit);
Celceius += 5;
}
You can use String.PadLeft function to pad spaces before your Fahrenheit values. You can give maximum length, 3 in your case, to pad necessary spaces. It will only pad spaces if length is smaller. You can check the details on below MSDN link.
http://msdn.microsoft.com/en-us/library/system.string.padleft%28v=vs.110%29.aspx
Below code will generate the list, but remember to use font which has equal size for each character such as "Courier New"
private void button1_Click(object sender, EventArgs e)
{
double Celceius = 0;
double Fahrenheit;
lblOUT.BackColor = Color.Red;
lblOUT.Text = "Celceius" + "".PadLeft(20) + "Fahrenheit";
while (Celceius <= 100)
{
Fahrenheit = 32 + (Celceius * 1.8);
lblOUT.Text += Environment.NewLine + Celceius.ToString().PadLeft(8,' ') + "".PadLeft(20) + Fahrenheit.ToString().PadLeft(10,' ');
Celceius += 5;
}
}
i'm trying to do a average speed of bugs killed per min. This is my code now but its throwing an error saying string input format is wrong. Any advice? I'm using C# for WPF.
//Score is the number of bugs hit
score.Text = (_killings * 1).ToString();
//Change it to integer
int x = Int32.Parse(score.Text);
int y = Int32.Parse(TBCountdown.Text); - this is where the error is showing
//Get the average speed by dividing number of bugs hit during the time
int average = (x / y);
//Displaying the average score by converting int to string
averagescore.Text = average.ToString();
For more information, i'm using a dispatcher timer and this is my code for the timer.
TBCountdown.Text = string.Format("00:0{0}:0{1}", time / 60, time % 60);
There are a couple of things that are wrong with your code, I am presuming that you are incrementing a variable and using it to create an elapsed time of some sort. The first thing to state is that Ed S. is correct and you should not be using your UI to store your value, create a backing variable and work with that. As far as your issues: the first one that comes to mind that I mentioned in my comments is that you are trying to convert a string that looks like a TimeSpan to an integer, the second is that your Format String will not convert to a DateTime Object it comes up with a Format Exception Error. I was able to get your code to work by changing your Timer's Tick eventhandler to this.
DateTime temp = DateTime.Parse(string.Format("00:{0}:{1}", time / 60, time % 60));
TBCountdown.Text = temp.ToString("00:mm:ss");
and you can use something like this to get your Y value (you did not respond to me about what information you were wanting for value)
int y = (int)TimeSpan.Parse(TBCountdown.Text).TotalSeconds;
There is a lot of conjecture here about what you want, if this isn't correct please let us know.
This is how you format the textbox:
TBCountdown.Text = string.Format("00:0{0}:0{1}", time / 60, time % 60);
And then you try to parse that as an int. Well, it's not an int. Parse it back as a DateTime or, better yet, just use the variable you already have (time). In general it is a poor idea to rely on your UI for storing your data. The UI is for display.
int y = time;
TBCountdown.Text = string.Format("00:0{0}:0{1}", (time / 60).ToString(), (time % 60).ToString());
remember this is a string function
I am trying to make a small pizza order form, but I have a problem with the calculations. After selecting a pizza, the unit price and total calculations are OK but selecting additions introduces a problem. After changing the NumericUpDown value, the calories are not correct (all units have constant prices and calories). The NumericUpDown's name is numberofunit. How can I calculate them?
if (pepper.Checked)
{
string peppereklendi =
Convert.ToString(Convert.ToDouble(unitprice.Text)+ pepperprice);
unitprice.Text = peppereklendi;
total.Text =
Convert.ToString(Convert.ToDecimal(unitprice.Text) * numberofunit.Value);
string pepperkaloriekle =
Convert.ToString(Convert.ToInt16(gizlikalori.Text) + pepperkalori);
gizlikalori.Text = pepperkaloriekle;
amountofcalorie.Text =
Convert.ToString(Convert.ToDecimal(gizlikalori.Text) * numberofunit.Value);
}
else
{
string peppereklendi = unitprice.Text;
unitprice.Text =
Convert.ToString(Convert.ToDouble(peppereklendi) - pepperprice);
total.Text = Convert.ToString(Convert.ToDecimal(unitprice.Text) * numberofunit.Value);
string pepperkaloriekle = gizlikalori.Text;
gizlikalori.Text =
Convert.ToString(Convert.ToDouble(pepperkaloriekle) - pepperkalori);
amountofcalorie.Text =
Convert.ToString(Convert.ToDecimal(gizlikalori.Text) * numberofunit.Value);
}
This Code is pepper's checkbox code.
This is the form of my application.
You should really try to separate the calculation logic from the UI logic (the form). Then the things will become much clearer:
// Get values from the text boxes
decimal up = Convert.ToDecimal(unitprice.Text);
decimal calories = Convert.ToDecimal(gizlikalori.Text);
decimal tot, totCalories;
// Do the calculation
if (pepper.Checked) {
up = up + pepperprice;
calories = calories + pepperkalori;
}
tot = up * numberofunit.Value;
totCalories = calories * numberofunit.Value;
// Assign the results to text boxes
unitprice.Text = up.ToString();
total.Text = tot.ToString();
gizlikalori.Text = calories.ToString();
amountofcalorie.Text = totCalories.ToString();
What you do wrong, is that you subtract the pepper price and pepper calories from the unit price and the unit calories if no pepper is selected. However, the unit price (and calories) are without the pepper already!
I do not see when you are performing this calculation, however if you perform it every time you are increasing the number of units, then you would be adding the pepper price each time! It would probaly be better to have a separate variable for the base unit price that remains unchanged when you check additions. Then always start the calculation from the base unit price.
In addition, you are mixing many different number types. This makes no sense.
The next step to enhance the code even more would be to create a separate class for the calculations. You could also use data binding. This would remove completely the need for doing conversions. See my answer to the following post
: manipulating-textbox-variables-in-calculations