1

I've attempted this many times and seem to just be spinning my wheels. How do I properly write the tax bracket and amount as variables that people could input different income amounts and it do the calculation in the code rather than just writing it out like I did here in the code?

I was able to make more progress as to what I'm trying to get at. I need help with how I assign these variables and how to write the output correctly.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Part_B_TaxBracket
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnCalculate_Click(object sender, EventArgs e)
        {
            //variables
            string status;
            string incomeasstring;
            string rateasstring;
             
            double income;  //to be input 
            double rate;     //to be calculated
            double tax;   //to be calculated

            double result;  // to be calculated            
            
           //process input
           if(status == "single")
            {
                if(income <= 9275)
                {
                    result = (income * .10);
                }
                if (income >= 9276 && income <= 37650)
                {
                    result = (income * .15);
                }
            }
            if (status == "married")
            {
                if (income <= 18550)
                {
                    result = (income * .10);
                }
            }
            if(income >=18551 && income <= 75300)
            {
                    result = (income * .15);
            }
        }
            //output the results
            lblresult.Text  = ("Your tax rate is {0} and taxes owed of {1}.", rate, tax);

        }
    }
}
Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
  • Not sure exactly what you're trying to achieve, could you explain a bit more? – Krystian Borysewicz Jul 03 '20 at 18:14
  • I think you should either roll back your question to it's initial form (as it's a bit more clear than the current version which has some new issues of its own and also omits most of the tests you were attempting to perflrm) or perhaps update the question to be a consolidation of the two in full form – pinkfloydx33 Jul 04 '20 at 13:35

3 Answers3

0

If you simply want your code to look better:

  • firstly what you can do is divide the income by two if status is married, this way you don't check the status AND the income each time;

  • and secondly, if you use "else if" instead of if, you get a much cleaner code. You first check if the income is less than 9275, then if you put "else if", it will know that the income is higher that 9275 and so on.

---------------------- EDIT ------------------------

The thing is, this tax brackets or tax rates cannot be calculated, you just decide it on the income amount. So no matter what, you will have this many if statements in which you decide the rate.

Now I see that the taxes owed are income * rate, so I cannot divide the income by 2 at the beginning. What I can do tho, is have a separate variable, incomePerPerson, and have that be income / 2, to help reduce the code inside each if.

At the end, you calculate the taxes and show that text in your label:

        double income = double.Parse(txtIncome.Text);
        string status = txtStatus.Text;

        //to be calculated
        double rate;
        double tax;
        double incomePerPerson = income;

        //get the income per person if status is married
        if (status == "married")
            incomePerPerson = income / 2;

        //determine tax rate
        if (incomePerPerson <= 9275)
        {
            rate = 0.10;
        }
        else if (incomePerPerson <= 37650)
        {
            rate = 0.15;
        }
        else if (incomePerPerson <= 91150)
        { 
            rate = 0.25;
        }
        else if (incomePerPerson <= 190150)
        {
            rate = 0.28;
        }
        else if (incomePerPerson <= 413350)
        {
            rate = 0.33;
        }
        else if (incomePerPerson <= 415050)
        {
            rate = 0.35;
        }
        else
        {
            rate = 0.396;
        }

        //determine taxes
        tax = income * rate;

        //output the results
        lblresult.Text  = ("Your tax rate is {0} and taxes owed of {1}.", rate, tax);

if you find a way to calculate the rate based on income per person, then those if statements need to be replaced with that formula. I couldn't figure one out, so that is your homework :) without the formula, I think this is the most clean code you can write.

Nicholas
  • 87
  • 9
  • its a simple tax calculator. the user would enter their income in the text box (.net forms) and their status (single or married) then click the calculate button. I need to use if statements to then get the answer but I want to use variables rather than just type in the tax brackets myself. the tax brackets are 10% for income singe up to 9275 or married up to 18550 and 15% for single with income between 9276 and 37,650 or married between 18551 and 75300. the rest doesn't matter as those brackets would be enough to understand the code and provide output. – user9666843 Jul 04 '20 at 06:29
  • I edited my answer so you have the rate in a separate variable and the taxes are now calculated. I hope this is what you wanted :D – Nicholas Jul 04 '20 at 11:16
0

First of all, I suggest extracting the tax rate calculation out into its own method. This will keep things clean and enable early returns from the method, allowing us to remove a bunch else statements. As long we check the ranges in order (either ascending or descending) we don't need to check both boundaries (ie >= x && <= y). This also makes the method testable which is something you should always consider -- the event handler for the button click isn't very testable.*

Second, I suggest you use decimal for the monetary calculations and not double. For more info on why, see this answer (by Jon Skeet) and this question (and it's duplicate). I'll note however that since this looks like a learning exercise, double should be fine. However keep in mind you wouldn't typically want to use them for monetary calculations.

Let's define our method. It will accept the status and our income. It will validate that the status is a valid value (and not say, Head Of Household) and throw an exception otherwise. Then we can process each range in order and return without needing to nest else statements:

public static decimal GetTaxRate(string status, decimal income)
{
    // we need to validate we have an appropriate status
    var comp = StringComparison.OrdinalIgnoreCase;

    if (!string.Equals(status, "married", comp) && !string.Equals(status, "single", comp))
        throw new InvalidOperationException("Invalid Status");

    if (string.Equals(status, "single", comp))
    {
        // note lack of "else" since we early return
        // note lack of " && income >= " which is implied
        if (income <= 9725) return 0.1m;
        if (income <= 37650) return 0.15m;
        if (income <= 91150) return 0.25m;
        if (income <= 190150) return 0.28m;
        if (income <= 413350) return 0.33m;
        if (income <= 415050) return 0.35m;

    }
    else // married
    {
        if (income <= 18550) return 0.1m;
        if (income <= 75300) return 0.15m;
        if (income <= 151900) return 0.25m;
        if (income <= 231450) return 0.28m;
        if (income <= 413350) return 0.33m;
        if (income <= 415050) return 0.35m;
    }

    // default for both
    return 0.396m;
}

Now we can call this function from your button click event handler:

string status = "single"; // get this some how
string incomeAsString = "1234.56"; // get this value some how

// validate that the income is a valid value
decimal income;
if (!decimal.TryParse(incomeAsString, out income)) 
{
   lblresult.Text = "Entered income is not a valid decimal value";
   return;
}

decimal taxRate = GetTaxRate(status, income); // calculate tax rate    
decimal totalTax = taxRate * income;

lblresult.Text = string.Format("Your tax rate is {0:P2} with taxes owed of {1:C2} (on income of {2:C2})", taxRate, totalTax, income);

I would suggest looking at ways to de-stringify your status variable. You could use an enum to represent the different states. You could even use a bool isSingle if you only ever plan on having the two options (though I'm not a fan of that option).

If you wanted to use some C#8 features, we could use a recursive pattern matching switch statement instead. I'm also using here C#7 digit separators (_) to make the numbers a bit more human readable:

// warning C# 8.0+
public static decimal GetTaxRate(string status, decimal income)
{
    // note: validation elided
    switch (status.ToLower(), income)
    {
        case ("single", decimal s) when s <= 9_725:
        case ("married", decimal m) when m <= 18_550:
            return 0.1M;
        case ("single", decimal s) when s <= 37_650:
        case ("married", decimal m) when m <= 75_300:
            return 0.15M;
        case ("single", decimal s) when s <= 91_150:
        case ("married", decimal m) when m <= 151_900:
            return 0.25m;
        case ("single", decimal s) when s <= 190_150:
        case ("married", decimal m) when m <= 231_450:
            return 0.28m;
        case (_, decimal i) when i <= 413_350:
            return 0.33m;
        case (_, decimal i) when i <= 415_050:
            return 0.35m;
        default:
            return 0.396m;
    }
}

In C#9 we'll be able to make use of relational patterns within switch expressions (see SharpLab example)

// warning C# 9.0
public static decimal GetTaxRate(string status, decimal income)
{
    // note: validation elided
    if (string.Equals(status, "single", StringComparison.OrdinalIgnoreCase))
    {
        return income switch {
            <= 9725 => 0.1M,
            <= 37650 => 0.15M,
            <= 91150 => 0.25M,
            <= 190150 => 0.28M,
            <= 413350 => 0.33M,
            <= 415050 => 0.35M,
            _ => 0.396M // default  
        };
    }
    
   // married
   return income switch {
        <= 18550 => 0.1M,
        <= 75300 => 0.15M,
        <= 151900 => 0.25M,
        <= 231450 => 0.28M,
        <= 413350 => 0.33M,
        <= 415050 => 0.35M,
        _ => 0.396M // default     
    };
}

Note: m and M are the suffixes used to designate a decimal literal. The casing does not matter--they are interchangable

* The event handler can be manually tested and validated (someone eyeballing the label text) but ideally you'd want to be able to use tools pole xUnit where you can define automated cases.

pinkfloydx33
  • 11,863
  • 3
  • 46
  • 63
-1

I don't have C# but I did previously program in C and I know that you have a Switch command available and I would recommend that. You set up your switch so that you test the highest value first and then just work your way down the maximums.

Here's some sample code in PowerShell which is close to C# which lays out the logic.

$Status = "single"
$income = 190151

If ($Status -eq "single") {
  Switch ($income) {
   {$_ -gt 415050 } { "Tax bracket is 39.6%";Break}
   {$_ -gt 413350 } { "Tax bracket is 35% with taxes of 144,672.85" ; Break }
   {$_ -gt 190150 } { "Tax bracket is 33% with taxes of  82,500.00" ; Break }
   Default { "Table Not Complete"}
  }

}
Else {
  #*** Married Code Here ***
}

Note the $_ is PowerShell shortcut for $Income, you'll of course have to adjust to C#

HTH

RetiredGeek
  • 2,980
  • 1
  • 7
  • 21