I am working on a employee paycheck calculator using several private methods. The methods will determine overtime hours and regular hours. I also must create methods for regular pay and overtime pay. My question is can I feed the results from the hours methods into the methods that will determine pay? If that is possible, how would it work? The method in question is CalculateBasePayAmount--can I pass a result from another method into here?
Here is a look at what I've got so far. Thanks for any help anyone could provide!
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
//Determine Hours Method
private decimal DetermineBasePayHours(decimal parhoursWorked)
{
decimal baseHours = 0;
decimal overtimeHours = 0;
if (parhoursWorked <= 40)
{
baseHours = parhoursWorked;
}
else if (parhoursWorked > 40)
{
overtimeHours = parhoursWorked - 40;
baseHours = parhoursWorked - overtimeHours ;
}
return baseHours;
}
private decimal DetermineOverTimeHours(decimal parHoursWorked, string parCategory)
{
decimal overtimeHours = 0;
if (parHoursWorked > 40 && parCategory!="MGR")
{
overtimeHours = parHoursWorked - 40;
}
return overtimeHours;
}
private decimal CalculateBasePayAmount(decimal basePayHours, string parCategory)
{
decimal basePay = 0;
decimal mgrWage = 20;
decimal salesWage = 15;
decimal staffWage = 10;
basePayHours= DetermineBasePayHours(basePayHours);
if(parCategory == "MGR" && basePayHours > 40)
{
basePay = 40 * mgrWage;
}
else
{
basePay = basePayHours * mgrWage;
}
if (parCategory =="SR")
{
basePay = basePayHours * salesWage;
}
else if (parCategory == "STF")
{
basePay = basePayHours * staffWage;
}
return basePay;
}
protected void butCalcPay_Click(object sender, EventArgs e)
{
////1. Declare Variables
//decimal mgrWage = 20;
//decimal salesWage = 15;
//decimal staffWage = 10;
//decimal basePay = 0M;
//decimal salesOvertime = 22.50M;
//decimal staffOvertime = 15;
//decimal overtimeHours = 0;
//decimal overtimePay = 0;
//decimal totalPay = 0;
decimal totalHours = 0;
decimal bpHours;
decimal otHours;
string empCat;
decimal basePay;
//2. Get Values for Variables
totalHours = Convert.ToDecimal(txtNumberHours.Text);
empCat = Convert.ToString(ddlCategory.SelectedValue);
// 3. Methods Called
bpHours = DetermineBasePayHours(totalHours);
otHours = DetermineOverTimeHours(totalHours, empCat);
basePay = CalculateBasePayAmount(totalHours, empCat);
// 4. Display Results
lblbasePay.Text = "Base Pay " + basePay.ToString("C");e here
can I feed the results from the hours methods into the methods that will determine pay?
In a manner of speaking, yes. Though I think the confusion is coming from the way you describe it and the terminology you use.
It's not entirely clear to me what specific values you're looking for in this case, but it looks like your methods essentially just accept some values, run some calculations, and return some values. Any code which call those functions will then get those returned values and can use them to call other functions. As a contrived example:
private int Method1(int someValue)
{
// perform some calculation, then...
return anotherValue;
}
private int Method2(int someValue)
{
// perform some calculation, then...
return anotherValue;
}
Then consuming code would be able to use those functions to perform larger calculations:
var calculatedValue = Method1(5);
var furtherCalculatedValue = Method2(calculatedValue);
This essentially "feeds the results" of the first function into the second function, in the sense that the result of the first function is then used as an input for the second function. The functions don't have any knowledge of each other, they don't "feed data to each other", in this case they simply return values based on calculations. Consuming code can choose to use the result of one function as a parameter to another function.
You do need to read more on programming and how/why we have methods that return values that the ones you mentioned above. Using your code above you'll want to use their values like this:
// basePayHours is the decimal amount returned by DetermineBasePayHours.
var basePayHours = DetermineBasePayHours(parhoursWorked);
// overTimeHours is the decimal amount returned by DetermineOverTimeHours.
var overTimeHours = DetermineOverTimeHours(parHoursWorked, parCategory);
// basePayAmount is the decimal amount returned by CalculateBasePayAmount.
var basePayAmount = CalculateBasePayAmount(basePayHours, parCategory);
delegate can also be used when a method is needed from another one .
Related
I have a textbox on my design form that have multiple numbers of double data type. I have a class that has a method to calculate smallest difference (positive or negative) between two consecutive numbers.
public decimal FindSmallestPriceChange()
{
}
On my form there is a label to display the result and a button event that calls the above method to calculate and display the smallest change between consecutive numbers in the text box.
private void btnSmallest_Click(object sender, EventArgs e)
{
lblSmallest.Text = aAnalyzer.FindSmallestPriceChange().ToString();
}
I have an array mentioned in the form class :
decimal[] prices = Array.ConvertAll(stringPrices, decimal.Parse);
I know I have to use for loop in my FindSmallest method but I don't know how to use the elements from the text box on design form in my separate class.
Can someone guide me on the right path on this.
The structure could be something like the following.
private void btnSmallest_Click(object sender, EventArgs e)
{
var stringPrices = new List<string>();
stringPrices.Add(comboBox1.Text);
stringPrices.Add(comboBox2.Text);
//TODO add error handling
decimal[] prices = Array.ConvertAll(stringPrices, decimal.Parse);
lblSmallest.Text = aAnalyzer.FindSmallestPriceChange(prices).ToString();
}
(...)
public static decimal FindSmallestPriceChange(IEnumerable<decimal> prices)
{
// There are many ways to do this. Here is one.
var sorted = prices.ToList();
sorted.Sort();
if( prices.Count() < 2 ) return 0;
decimal min = sorted[1] - sorted[0];
for(int i = 2; i < sorted.Count() - 1 ; i++ ) {
var diff = sorted[i-1] - sorted[i];
if( diff < min ) min = diff;
}
return min;
}
Test
Console.WriteLine(FindSmallestPriceChange(new []{66.6m}));
Console.WriteLine(FindSmallestPriceChange(new []{1m, 2m}));
Console.WriteLine(FindSmallestPriceChange(new []{1.1m, 4.4m, 2.2m}));
Console.WriteLine(FindSmallestPriceChange(new []{4.4m, -1.1m, 0m, 1.1m, 2.2m, }));
Output
0
1
1.1
-1.1
Currently I am trying to find the thirteen adjacent digits in a 1000-digit number that will have the greatest product.Now I written a function which is supposed to multiply the desired number of adjacent digits to be multiplied and later store the product in a list . The two parameters the functions takes are the desired number of adjacent digits and string which contains the number. But for some reason it wont stop running.
public static void giveProduct(int quantity, string word)
{
int product = 1;
int place1 = 0;
int place2 = quantity - 1;
int temp = 1;
string temp2;
while (place2 < word.Length)
{
for (int i = place1; i < place2; i++)
{
temp2 = word[i].ToString();
temp = Int32.Parse(temp2);
product = product * i;
}
products.Add(product);
product = 1;
place1 += quantity;
place2 += quantity;
}
}
Can't reproduce your issue, the method terminates "correctly" for any sensible input.
But anyway, that is far from the only issue in your implementation. Your method is not calculating correctly the maximum product because you are skipping through the string quantity characters at a time. You should be skipping one character at a time and taking the quantity long substring starting at that position.
For string 123456 and quantity 3 you are evaluating 123 and 456. You should be checking 123, 234, 345, etc.
Also, get into the habit of:
Validating inputs
Writing helper methods. The shorter a method, the harder to introduce a bug in it.
Consider all possible values that word can represent? Have you considered { 1234 }? (note the leading and trailing spaces). How about -1234?
Prepare for the worse. Make your code robust so its able to handle incorrect data; your program will crash if the input is 123$5.
With all that in mind, consider the following implementation:
First a simple helper method that evaluates the product of all the digits of a given string representing a number.
private static bool TryMultiplyDigits(string number, out int product)
{
Debug.Assert(number != null && number.Length > 0);
product = 1;
foreach (var c in number)
{
int digit;
if (int.TryParse(c.ToString(), out digit))
{
product *= digit;
}
else
return false;
}
return true;
}
Ok great, this method will give us the correct product or simply tell us it can't evaluate it for any input.
Now, a method that will create all the possible subtrings and return the maximum product found:
public static int GetMaximumProduct(string number, int quantity)
{
if (number == null)
throw new ArgumentNullException(nameof(number));
if (quantity < 1)
throw new ArgumentOutOfRangeException(nameof(quantity));
if (quantity > number.Length)
throw new ArgumentException($"{nameof(quantity)} can not be greater than the length of {nameof(number)}.");
var normalizedNumber = number.Trim();
normalizedNumber = normalizedNumber.StartsWith("-") ? normalizedNumber.Substring(1) : normalizedNumber;
if (string.IsEmpty(normalizedNumber))
{
product = 0;
return true;
}
var maximumProduct = 0;
for (var i = 0; i < normalizedNumber.Length - (quantity - 1); i++)
{
int currentProduct;
if (TryMultiplyDigits(normalizedNumber.Substring(i, quantity), out currentProduct))
{
if (currentProduct > maximumProduct)
{
maximumProduct = currentProduct;
}
}
else
{
throw new FormatException("Specified number does not have the correct format.");
}
}
return maximumProduct;
}
And we're done!
Getting this error at futureValue = this.CalculateFutureValue(futureValue, monthlyInvestment, monthlyInterestRate, months);and I'm having trouble figuring out how to fix it. When I look up the error online most of the answers say to make the method decimal instead of void so it can have a return type.
But in part of the requirements for the code "rework the CalculateFutureValue method by making it a void function and adding a fourth parameter representing the future value amount to be returned by this method."
private void btnCalculate_Click(object sender, EventArgs e)
{
decimal monthlyInvestment = Convert.ToDecimal(txtMonthlyInvestment.Text);
decimal yearlyInterestRate = Convert.ToDecimal(txtInterestRate.Text);
int years = Convert.ToInt32(txtYears.Text);
int months = years * 12;
decimal monthlyInterestRate = yearlyInterestRate / 12 / 100;
decimal futureValue = 0m;
futureValue = this.CalculateFutureValue(futureValue, monthlyInvestment, monthlyInterestRate, months);
txtFutureValue.Text = futureValue.ToString("c");
txtMonthlyInvestment.Focus();
}
/
private void CalculateFutureValue(decimal futureValue, decimal monthlyInvestment, decimal monthlyInterestRate, int months)
{
for (int i = 0; i < months; i++)
{
futureValue = (futureValue + monthlyInvestment) * (1 + monthlyInterestRate);
}
}
Here is what they mean by the requirement: instead of this
decimal ComputeSomething(decimal x, decimal y) {
return x*x + y*y;
}
...
decimal result = ComputeSomething(10.234M, 20.5M);
do this:
void ComputeSomething(decimal x, decimal y, out res) {
res = x*x + y*y;
}
...
decimal result;
ComputeSomething(10.234M, 20.5M, out result);
Note the out qualifier in front of the additional parameter res. This means that the parameter is "output", i.e. your method must assign it some value before completion.
The assignment to res inside ComputeSomething will become an assignment to variable result.
You need to pass the variable by reference:
private void CalculateFutureValue(ref decimal futureValue, decimal monthlyInvestment, decimal monthlyInterestRate, int months){ ... }
and
this.CalculateFutureValue(ref futureValue, monthlyInvestment, monthlyInterestRate, months);
See this documentation.
If futureValue had not been initialized with a value before passing it to CalculateFutureValue, the out keyword would have needed to be used in place of ref.
Ok. So I'm trying to have a program.. where the user enters his salary and then the program will calculate his salary for the next four years with a raise of 2.5% each year.
I feel like I have done this completely wrong, because my loop is only calculating one time.. its not even showing four salary's.. not to mention having them each raised 2.5% each time.
private void btnDisplay_Click(object sender, EventArgs e)
{
int count;
for (count = 1; count <= 4; count++)
{
decimal Raise;
decimal Salary;
decimal Sum;
decimal Total;
Raise = Convert.ToDecimal(0.025);
Salary = Convert.ToDecimal(txtSalary.Text);
Sum = Salary * Raise;
Total = Salary + Sum;
label2.Text = Total.ToString("c");
}
txtSalary is whatever the user entered salary is.
label2 is the display of the calculation.
---------------- UPDATE: I have updated the code with the final product. Thanks to everyone for helping out especially Patrick Hofman! You are the best.. I couldn't have done it without you. ------------------------
private void btnDisplay_Click(object sender, EventArgs e)
{
decimal salary = Convert.ToDecimal(txtSalary.Text);
decimal raise = 0.025m;
decimal previous = salary;
for (decimal year = 1; year <= 4; year++)
{
decimal sum = previous * (1 + raise);
previous = sum;
listBox1.Items.Add(sum.ToString("c"));
}
I think you should have something like this:
private void btnDisplay_Click(object sender, EventArgs e)
{
decimal salary = Convert.ToDecimal(txtSalary.Text);
decimal raise = 0.025m;
decimal total = 0;
decimal previous = salary;
listBox1.Items.Add("Start: {0:N2}", salary);
for (int year = 1; year <= 4; year++)
{
decimal sum = previous * (1 + raise);
previous = sum;
total += sum;
listBox1.Items.Add("Year {0}: {1:N2}", year, sum);
}
listBox1.Items.Add("Total: {0:N2}", total);
}
Note I made some changes to the variables. Some were moved to keep them over the for loop.
The steps:
Start with setting the start point (previous) to the salary.
For each year, multiply the previous year's salary with the raise percentage +1.
Set the previous and add that year's salary to the total.
Show the total in the label.
int count;
Salary = Convert.ToDecimal(txtSalary.Text);
for (count = 1; count <= 4; count++)
{
Salary *= 1.025m;
}
label2.Text = Salary.ToString("c");
You need to make sure you're retrieve the salary once at teh beginning and don't overwrite it till the end.
Problem 1: You are declaring the variables inside the forloop.so each time they are initialised with their default values.
Solution 1: inorder to retain their last assigned values you need to move the declaration of the variables outside the loop.
Problem 2: you are not able to see the results/changes as you are updating the label inside the for loop without any delay.so evatually you can only see the last calculated result.
Solution2: You need to either create 4 different labels to show the 4 different results or you need to wait for some time for updating the label results in each iteration by using timer functionality.
Try This: using LabelArray
Label[] lblSalaries = new Label[4];
private void CreateControls()
{
int x = 0, y = 10;
for (int i = 0; i < lblSalaries.Length;i++ )
{
lblSalaries[i] = new Label();
x += 60;
lblSalaries[i].Size = new System.Drawing.Size(50, 30);
lblSalaries[i].Location = new System.Drawing.Point(x,y);
Controls.Add(lblSalaries[i]);
}
}
private void btnDisplay_Click(object sender, EventArgs e)
{
int count;
decimal Raise;
decimal Salary;
decimal Sum;
decimal Total;
CreateControls();
for (count = 1; count <= 4; count++)
{
Raise = Convert.ToDecimal(0.025);
Salary = Convert.ToDecimal(txtSalary.Text);
Sum = Salary * Raise;
Total = Salary + Sum;
lblSalaries[count-1].Text = Total.ToString("c");
}
}
I want to make my application to calculate a discount price. This is how I find my discount price, but I have a little problem (logic problem):
private void UpdateDiscount(object sender, EventArgs e)
{
decimal actualPrice = 0;
decimal discount = 0;
int calculateDiscount = 0;
int totalDiscount = 0;
int afterDiscount = 0;
int totalAfterDiscount = 0;
int total = 0;
if (numericTextBox1.TextLength == 6)
{
this.numericUpDown2.Enabled = true;
discount = Convert.ToInt32(this.numericUpDown2.Value);
calculateDiscount = Convert.ToInt32(discount / 100);
totalDiscount = calculateDiscount;
if (!string.IsNullOrEmpty(this.numericTextBox3.Text.ToString()))
{
actualPrice = Convert.ToDecimal(this.numericTextBox3.Text);
}
else
{
numericTextBox3.Text = "";
}
afterDiscount = Convert.ToInt32(actualPrice * totalDiscount);
totalAfterDiscount = Convert.ToInt32(actualPrice);
total = Convert.ToInt32(totalAfterDiscount - afterDiscount);
if (numericUpDown2.Value > 0)
{
this.numericTextBox6.Text = total.ToString();
}
}
else if (numericTextBox1.TextLength != 6)
{
this.numericUpDown2.Enabled = false;
this.numericUpDown2.Value = 0;
this.numericTextBox6.Text = "";
}
else
{
actualPrice = 0;
discount = 0;
calculateDiscount = 0;
totalDiscount = 0;
afterDiscount = 0;
totalAfterDiscount = 0;
total = 0;
MessageBox.Show("There is no data based on your selection", "Error");
}
}
This is the result, the total after discount still same with the total price, even though I already give it discount value.
Given
a price P such that 0 <= P, and
a discount percentage D such that 0 <= D <= 100
you can compute the discount (markdown) MD that needs to be applied as
MD = P * (D/100)
You can then get the discounted price DP as
DP = P - MD
Given that, this should do you:
public static class DecimalHelpers
{
public static decimal ComputeDiscountedPrice( this decimal originalPrice , decimal percentDiscount )
{
// enforce preconditions
if ( originalPrice < 0m ) throw new ArgumentOutOfRangeException( "originalPrice" , "a price can't be negative!" ) ;
if ( percentDiscount < 0m ) throw new ArgumentOutOfRangeException( "percentDiscount" , "a discount can't be negative!" ) ;
if ( percentDiscount > 100m ) throw new ArgumentOutOfRangeException( "percentDiscount" , "a discount can't exceed 100%" ) ;
decimal markdown = Math.Round( originalPrice * ( percentDiscount / 100m) , 2 , MidpointRounding.ToEven ) ;
decimal discountedPrice = originalPrice - markdown ;
return discountedPrice ;
}
}
Don't use int (or Convert.ToInt32) when dealing with money.
See this
decimal discount = 10;
var calculateDiscount = Convert.ToInt32(discount / 100);
MessageBox.Show(calculateDiscount.ToString());
calculateDiscount will be 0 because 0.1 will be converted 0.
I suspect the problem is mostly due to the fact that you're using integers for everything. In particular, these two lines:
discount = Convert.ToInt32(this.numericUpDown2.Value);
calculateDiscount = Convert.ToInt32(discount / 100);
When you use 10 for "10%" as the discount, the second line there is actually resulting in a zero. This is because you are doing integer mathematics: integers can only be whole numbers, and when they have a number that is not whole they truncate it. In this case, discount / 100 in your example would be 0.1, which would get truncated to zero.
Instead of using int, I recommend using decimal for all financial transactions. I would replace most of your integer variable types throughout that function with decimal.
I think you're going to have problems with...
calculateDiscount = Convert.ToInt32(discount / 100);
Int (Integers) are whole numbers, they will be rounded down. If discount is less than 100 it will always be zero.
Avoid using double or floats for financial transactions as they can produce considerable floating point errors.
Using integers is good, as they are accurate and quick, HOWEVER you MUST always consider how numbers will be rounded, ensure the operands and results are always whole numbers.
If they are not whole numbers use the Decimal structure, which under the covers is comprised of three integers, but three times slower than using integers.
In most cases being 3 times slower than blindingly quick, still ends up being blindingly quick so when in doubt use Decimals.
if you want to get the Original Price from the Discounted Price and Discount Value. you can use this code
using System;
public class Program
{
public static void Main()
{
decimal discountedPrice = 280;
decimal discount = (decimal)0.20;
decimal originalPrice = discountedPrice / (decimal)(1-discount);
Console.WriteLine(originalPrice);
}
}```