C# 非常奇怪的行为:乘法给出了错误的答案

C# 非常奇怪的行为:乘法给出了错误的答案,c#,C#,我有很奇怪的问题。我有一个应用程序,客户将输入数量和价格,然后程序将自动计算。问题是,在某些时候,它给出了错误的数字,我有一个例子。在此之前,这是代码: void calculate_total() { int i; total_bill = 0; double pre_total; for (i = 0; i < row_count; i++) { TextBox[]

我有很奇怪的问题。我有一个应用程序,客户将输入数量和价格,然后程序将自动计算。问题是,在某些时候,它给出了错误的数字,我有一个例子。在此之前,这是代码:

    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();
        }
    } 
void计算_总计()
{
int i;
账单总额=0;
双倍预加总;
对于(i=0;i
例如:如果价格是3.8,数量是12,答案应该是45.6。然而,答案是:45.5559

这真是非常奇怪的行为。能帮忙吗


致以最良好的祝愿

这只是浮点类型精度有限的问题。如果比较值,则不能依赖“精确”值。你总是需要考虑某个“ε”差异。如果您搜索(比如)“比较浮点数”,可能会有很多关于这个问题的参考文献


此外,如果在循环中计算,这样的小偏差往往会增加。因此,与其将某个值加10倍,不如将该值的10倍加一倍。

这只是浮点类型精度有限的问题。如果比较值,则不能依赖“精确”值。你总是需要考虑某个“ε”差异。如果您搜索(比如)“比较浮点数”,可能会有很多关于这个问题的参考文献


此外,如果在循环中计算,这样的小偏差往往会增加。因此,例如,与其将某个值加10倍,不如将该值的10倍加一倍。

千万不要将double用于货币算术。double是一个浮点数,在执行数学运算时,有时会在将其渲染回以10为底以供显示时失去精度。这是因为浮点数在内存中的表示方式

您可以使用数据类型,该数据类型将保持货币小数点的准确性

这个问题有很多关于何时应该在小数点上使用双精度的讨论:

货币算术永远不要使用double。double是一个浮点数,在执行数学运算时,有时会在将其渲染回以10为底以供显示时失去精度。这是因为浮点数在内存中的表示方式

您可以使用数据类型,该数据类型将保持货币小数点的准确性

这个问题有很多关于何时应该在小数点上使用双精度的讨论:

定点数学中不要使用浮点。将变量更改为十进制

不要将浮点用于定点数学。将变量更改为
十进制

浮点算术。使用
System.Decimal
,因为它比
System.Double
更精确。。。确保在必要的地方浇铸。你不能用足够的方法来避免这些计算错误。浮点运算。使用
System.Decimal
,因为它比
System.Double
更精确。。。确保在必要的地方浇铸。您无法进行足够的强制转换以避免这些计算错误。十进制也是浮点。区别在于基准,而不是点是否固定。相反,你应该说不要在十进制数学中使用二进制。十进制也是浮点。区别在于基准,而不是点是否固定。相反,你应该说不要在十进制数学中使用二进制,但十进制也是如此。试着用十进制计算三分之一。它会四舍五入,但十进制也是如此。试着用十进制计算三分之一。它会四舍五入。
decimal
也是一个浮点数,在执行数学运算时,有时会丢失精度。@s选择十进制不是浮点数。根据C语言规范第4.1.7节:
十进制表示为96位整数,按十的幂进行缩放。
十进制
为m·10^e,
双精度
为m·2^e。这就是“浮点”的定义。@svick是正确的;它被称为“浮点”,因为。。。等等。。。小数点的位置是浮动的。二进制浮点是一个52位整数,按2的幂进行缩放。它们都是浮点数的原因是刻度不是固定为一个值。如果十进制的小数位数固定为一百万,则可以表示123.456789,但不能表示123.45678901,因为这将小数点移动了两位。
decimal
也是一个浮点数,在执行数学运算时,有时会失去精度。@svick decimal不是浮点数。根据C语言规范第4.1.7节:
十进制表示为96位整数,按十的幂进行缩放。
十进制
为m·10^e,
双精度
为m·2^e。这就是我们的定义?