3

I have this piece of code at the moment:

 totalCost = fuelPrice * purchaseVolume;
 totalCost = Math.Round(totalCost, 2);
 Console.WriteLine("Total Cost = £" + totalCost);

If the fuel price is 1.15 and the volume is 2, the console.writeline then displays the Total cost as £2.3, not 2.30 as I am trying to achieve. What am I doing wrong?

T.Rob
  • 31,522
  • 9
  • 59
  • 103
developer__c
  • 636
  • 3
  • 11
  • 31
  • 1
    Use decimal type for money computations - http://stackoverflow.com/questions/1165761/decimal-vs-double-which-one-should-i-use-and-when – KV Prajapati Oct 20 '11 at 11:29

6 Answers6

6

That you are rounding, not formatting :-)

you don't need the Math.Round, you need:

Console.WriteLine("Total Cost = £ {0:F2}", totalCost);

You can look at it in this way: the computer represent internally numbers in some formats. These formats are normally binary formats, and aren't "intellegible" by "mere mortals". double is one of these formats. It's a fixed-length format, so every double is 8 bytes long. When you want to print it somewhere, you have to "stringify" it (convert it to a format intellegible for humans). In C#/.NET this is normally done with the ToString() method that all the objects have.

Now, in a double 1.0 == 1.00 == 1. The extra zeros aren't saved (because they normally aren't important)

Math.Round "produces" a double with a maximum number of decimals (we will ignore the vagaries of double). So Math.Round(1.222, 2) == 1.22, but Math.Round(1.0, 2) == 1 So Math.Round is a function that from a double returns a double.

Console.WriteLine is something different. In this case it takes a double and stringify it (and show it to the console screen). When you stringify a number and tell the Console.WriteLine that you want 2 decimals after the ., it will show 2 decimals, even if there are zero decimals. So Console.WriteLine("{0:F2}", 1) will print 1.00. Probably Console.WriteLine uses the ToString method of double to do it. So in truth, it would be better to analyze the ToString method of double, because Console.WriteLine("Total Cost = £ {0:F2}", totalCost) is probably very similar internally to Console.WriteLine("Total Cost = £ {0}", totalCost.ToString("F2"));

I was forgetting. Do as AVD told you in a comment to your post. float and double are probably two of the greatest evils of Information Technology.

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • Ahh right I see, surely though the Math.Round method should work? – developer__c Oct 20 '11 at 11:20
  • @HTTP404 One thing is how a number is represented in memory (for example double), another thing is how it's showed to the screen. On the screen it's a `string`. So through the `Math.Round` you can obtain a "memory" number with **maximum** a certain number of digits (but remember that in a computer, 1.00 == 1.0 == 1 and it's saved as 1 (we will ignore exactly how doubles are saved in memory)). But to format it (to "stringify" it), you must specify the formatting to `Console.WriteLine` (or to the method `ToString()`) – xanatos Oct 20 '11 at 11:25
4

The point is that if you round 2.3 to the second digit you still get 2.3
To put it otherwise, 2.30 and 2.3 are the same number.

What you need is

Console.WriteLine("Total Cost = £{0:F2}", totalCost);

Check this article: .NET Format String 101

Paolo Tedesco
  • 55,237
  • 33
  • 144
  • 193
3

You have to invoke totalCost.ToString("format"). Look here

Wojteq
  • 1,173
  • 9
  • 23
3

to show two digits after the comma use this command:

Console.WriteLine(String.Format("Total Cost = £ {0}", totalCost.ToString("n2")));

I think the Math.Round is not what you need in this case.

Davide Piras
  • 43,984
  • 10
  • 98
  • 147
  • The round would still be required to force the amount to be an amount that is billable (e.g. £1.319 per litre, and 1 litre should charge £1.32 - the format string won't do that rounding for you). – Rowland Shaw Oct 20 '11 at 11:25
3

You need to format the number to get trailing zeros on the fractional part, for example:

Console.WriteLine(string.Format( "Total Cost = £{0:F2}", totalCost) );
Rowland Shaw
  • 37,700
  • 14
  • 97
  • 166
3

The case you describe is not a matter of rounding, but a matter of formatting. If you do this:

Console.WriteLine(string.Format("Total Cost = {0:c}" , totalCost)) 

You'll probably get what you want including putting the appropriate currency symbol depending on the locale

Icarus
  • 63,293
  • 14
  • 100
  • 115