-1

I am developing an app for a client. It should get some inputs from the console, like total meal price; plus, the second line should ask for the tip percentage. The third would ask for taxPercent.

I have the following code, but it fails one of two test cases. When I enter 15.50 for mealCoast, 15 percent for tip and 10% for tax, it passes the test case. However, if I enter 12.00 for mealCost, 20 for tip% and 8 for tax percent, it fails to meet the test case requirements.

Here you can see my code sample.

double mealCoast = double.Parse(Console.ReadLine());
        int tipPercent = int.Parse(Console.ReadLine());
        int taxPercent = int.Parse(Console.ReadLine());

        //Calculating % 
        tipPercent = Convert.ToInt16(mealCoast) * (tipPercent) / 100;
        taxPercent = Convert.ToInt16(mealCoast) * (taxPercent) / 100;

        int totalCast = Convert.ToInt16(mealCoast) + tipPercent + taxPercent;

        Console.WriteLine("The total meal cost is {0} dollars.", totalCast);

        Console.ReadKey();
Dev
  • 307
  • 1
  • 2
  • 12
  • 1
    surely percentages is n / 100 * number_percent_wanted = result. Are tips taxable? are you sure? – BugFinder Mar 29 '16 at 14:28
  • Add your inputs *with the expected and actual outputs*. What does your test case actually look like? – Matt Burland Mar 29 '16 at 14:28
  • 2
    As a side note [Decimal](https://msdn.microsoft.com/en-us/library/364x0z75.aspx) is more suited to handling currency that `double`. – Stephen Ross Mar 29 '16 at 14:30
  • you cast double to integer, it could work for 12.00, but not for 15.5 (you get 16 and you result is wrong) – Maksim Simkin Mar 29 '16 at 14:30
  • use `tipPercent = (int)(mealCoast * tipPercent / 100.0);` – Iłya Bursov Mar 29 '16 at 14:30
  • 7
    You are casting to `int` all over the place which makes no sense. Casting doesn't round, it truncates. So keep everything in `double` (or better yet `decimal`) until you have your final result and then `Round` if needed. As it currently stands, you `15.50` test case doesn't make any sense. It returns `18` which is way off (it should be 19.38 rounded to the nearest cent) – Matt Burland Mar 29 '16 at 14:31
  • first test case user enters 15.50 total meal 15 for 15 % tip then 10 for tax percent finally it sums up to 19 usd however second case 12.00 for mealPrice , 20 for tip and 8 for tax fails to produce required output output should be 15 usd it prints 14 usd strange thing taxtPercent variable become 0 – Dev Mar 29 '16 at 14:34
  • 1
    Are you sure the 15.50 line truly comes out correct? as it told me 19 dollars. simple maths says 15.5/100 = .155, * 15 = 2.325, *10 = 1.55, so 15.5 +2.325+1.55 = 19.375 - your app clearly fails on the first too – BugFinder Mar 29 '16 at 14:34
  • 1
    **Never** use a floating-point type (`double` or `float`) to represent currency. **Always** use `decimal`. – Ondrej Tucny Mar 29 '16 at 14:34
  • 1
    tax can be a decimal too - for years in the uk it was 17.5% – BugFinder Mar 29 '16 at 14:35
  • *"strange thing taxtPercent variable become 0"*, of course it does, because `12*8 = 98` and `98 / 100 = 0` when you do **integer division** – Matt Burland Mar 29 '16 at 14:40

2 Answers2

1

A couple of possible issues:

Firstly, beware of the integer division. It basically means that if you divide int data type by int data type, you will get int result. Note that you use int all over the places, which is not a good practice - in your application, likely you don't want that. But rather you want to be precise in your money-involved computation. Thus, I suggest to use double - or better - decimal for your data computation

Secondly, beware of the non-convertible string to the respective number data type (be it int or floating point like double). Don't use Parse, but use TryParse to ensure the input is convertible.

By using correct data type and correct way to process the data, you would already half-way accomplishing your goals. Putting them into code, this is how it may look like:

decimal mealCoast, tipPercent, taxPercent; //use decimal, probably is best
bool mealCoastResult = decimal.TryParse(Console.ReadLine(), out mealCoast);
bool tipPercentResult = decimal.TryParse(Console.ReadLine(), out tipPercent); //use TryParse
bool taxPercentResult = decimal.TryParse(Console.ReadLine(), out taxPercent);

//Input checking, check any parsing error
if (!mealCoastResult || !tipPercentResult || !taxPercentResult){
    //do some error handlers
    return; //probably don't continue is good
}
//you could also put some while loop

//Calculating % 
tipPercent = mealCoast * tipPercent / 100;
taxPercent = mealCoast * taxPercent / 100;

decimal grandTotal = mealCoast + tipPercent + taxPercent;
Console.WriteLine("The total meal cost is {0} dollars.", grandTotal);
Console.ReadKey();
Ian
  • 30,182
  • 19
  • 69
  • 107
  • You should probably either `Round` `grandTotal` to 2 d.p. or perhaps `Floor` it, since you can't really expect people to pay in fractions of a cent. – Matt Burland Mar 29 '16 at 14:41
  • @MattBurland ah yes, when it is used for payment, probably 2 decimal points would most probably be sufficient – Ian Mar 29 '16 at 14:43
  • Thanks Ian it worked Just rounded gandTotal both test cases passed but really how stupid i was – Dev Mar 29 '16 at 14:43
  • @Dev ah yes, your mistake is a *very common* mistake, in fact. Also, note Matt Burland comment above. If you use `grandTotal` for payment, rounding up to the 2 decimal point is actually OK. – Ian Mar 29 '16 at 14:45
1

however second case 12.00 for mealPrice , 20 for tip and 8 for tax fails to produce required output output should be 15 usd it prints 14 usd strange thing taxtPercent variable become 0

Let's have a look at your code for the example:

double mealCoast = double.Parse(Console.ReadLine()); // mealCoast = 12.
int tipPercent = int.Parse(Console.ReadLine()); // tipPercent = 20
int taxPercent = int.Parse(Console.ReadLine()); // taxPercent = 8

//Calculating % 
// Convert.ToInt16(mealCoast) will give you 12
// you are using integer division here, no digits preserved after period.
tipPercent = Convert.ToInt16(mealCoast) * (tipPercent) / 100; // 12 * 20 / 100 = 2
taxPercent = Convert.ToInt16(mealCoast) * (taxPercent) / 100; // 12 * 8 / 100 = 0

// 12 + 2 + 0 = 14
int totalCast = Convert.ToInt16(mealCoast) + tipPercent + taxPercent; // 14
Console.WriteLine("The total meal cost is {0} dollars.", totalCast); 

Console.ReadKey();

/ operator is integer division if its operands are of integer types. It will truncate all the decimal digits after period. This also does not depend on the type of the variable you are assigning result at. Take a look at decimal or double data types.

Ivan Gritsenko
  • 4,166
  • 2
  • 20
  • 34