0

I have very strange problems. I have one application where the customer will enter the qusntity and the price, then the program will calculate automatically. Problem is that in some time it gives incorrect numbers, I have one example. Before, this is code:

    void calculate_total()
    {
        int i;
        total_bill = 0;
        double pre_total;
        for (i = 0; i < row_count; i++)
        {
            TextBox[] textbox_item_array = new TextBox[6];
            textbox_item_array = (TextBox[])(item_textbox[i]);
            if (textbox_item_array[0].Text != "" && textbox_item_array[4].Text != "" && textbox_item_array[3].Text != "")
            {
                pre_total = System.Convert.ToInt32(textbox_item_array[4].Text) * System.Convert.ToDouble(textbox_item_array[3].Text);
                total_bill = total_bill + pre_total;
            }
        }
        if (double.TryParse(textbox_bill_discount.Text, out bill.bill_discount) == true)
        {
            textbox_bill_total.Text = total_bill.ToString();
            final_total = total_bill - bill.bill_discount;
            textbox_bill_final_total.Text = final_total.ToString();
        }
        else
        {
            textbox_bill_discount.Text = "";
            final_total = total_bill;
            textbox_bill_total.Text = total_bill.ToString();
            textbox_bill_final_total.Text = final_total.ToString();
        }
    } 

Example of that: if the price is 3.8 and the quantity is 12, the answer should be 45.6. However, the answer is: 45.5555555559.

It is really very strange behavior. Can any help please!!

Best Regards.

Michael S. Scherotter
  • 10,715
  • 3
  • 34
  • 57
user2103335
  • 63
  • 4
  • 13
  • 1
    Floating point airthmetic !!!! [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) . – AllTooSir Jun 08 '13 at 21:06
  • Use `System.Decimal` as it has more precision than `System.Double`... make sure to cast where necessary. You can't cast enough to avoid these miscalculations. – Mike de Klerk Jun 08 '13 at 21:07

3 Answers3

4

Never use double for currency arithmetic. A double is a floating point number and when math is performed you sometimes lose precision when rendering it back to base 10 for display. This is because of how the numbers are represented in memory for a floating point number.

You can use the System.Decimal data type which will keep your decimal points for currency accurate.

This SO question has a lot of discussion on when you should use the double over the decimal: When should I use double instead of decimal?

Community
  • 1
  • 1
John Koerner
  • 37,428
  • 8
  • 84
  • 134
  • `decimal` is also a floating point number and when math is performed, you sometimes lose precision. – svick Jun 09 '13 at 11:33
  • @svick A decimal is not a floating point number. From the C# language spec, section 4.1.7: `A decimal is represented as a 96-bit integer scaled by a power of ten.` – John Koerner Jun 10 '13 at 02:15
  • `decimal` is m · 10^e, `double` is m · 2^e. That's the definition of “floating point”. – svick Jun 10 '13 at 12:34
  • @svick is correct; it's called "floating point" because... wait for it... the position of the decimal point floats around. A binary float is a 52 bit integer scaled by a power of two. What makes them both *floating* point is that *the scale is not fixed to one value*. If the scale in decimal were fixed to say one million then you could represent 123.456789, but not 123.45678901 because that moved the decimal point by two places. – Eric Lippert Jun 10 '13 at 13:40
3

It's simply a matter of limited precision of floating point types. If you compare values you cannot rely on an "exact" value. You always need to consider a certain "epsilon" difference. There are probably numerous references to this problem if you search for, say, "compare floating point numbers".

Furthermore, if calculating in a loop, such small deviations tend to grow. Hence, instead of, for instance, adding 10 times a certain value, it's better to add one time the tenfold of the value.

JeffRSon
  • 10,404
  • 4
  • 26
  • 51
-1

Don't use floating point for fixed-point math. Change your variables to Decimal.

STLDev
  • 5,950
  • 25
  • 36
  • 1
    Decimal is also floating point. The difference is the base, not whether the point is fixed. you should instead say don't use binary for decimal math. – Eric Lippert Jun 09 '13 at 05:05