Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将双精度值乘以100.0会导致舍入误差吗?_C#_.net_Math - Fatal编程技术网

C# 将双精度值乘以100.0会导致舍入误差吗?

C# 将双精度值乘以100.0会导致舍入误差吗?,c#,.net,math,C#,.net,Math,这就是我正在做的,99.999%的时间都有效: ((int)(customerBatch.Amount * 100.0)).ToString() 金额值是双倍的。我正在尝试将值以便士的形式写入文本文件,以便传输到服务器进行处理。该数值的精度不得超过2位数 如果使用580.55作为金额,则此行代码将返回58054作为字符串值 此代码以64位格式在web服务器上运行 有什么想法吗?你真的应该用十进制计算货币 ((int)(580.55m * 100.0m)).ToString().Dump();

这就是我正在做的,99.999%的时间都有效:

((int)(customerBatch.Amount * 100.0)).ToString()
金额值是双倍的。我正在尝试将值以便士的形式写入文本文件,以便传输到服务器进行处理。该数值的精度不得超过2位数

如果使用580.55作为金额,则此行代码将返回58054作为字符串值

此代码以64位格式在web服务器上运行


有什么想法吗?

你真的应该用十进制计算货币

((int)(580.55m * 100.0m)).ToString().Dump();

您可以使用
decimal
值进行精确计算。Double是浮点数,在计算过程中不能保证精确。

我的建议是将该值存储为整数,并取
美元=pennies/100
美分=pennies%100
。这将完全避免舍入错误

((int)(580.55m * 100.0m)).ToString().Dump();
编辑:当我写这篇文章时,我没有看到你不能更改数字格式。最好的答案可能是使用其他人建议的圆形方法


编辑2:正如其他人所指出的,最好使用某种定点十进制变量。这比我原来的解决方案要好,因为它将小数点的位置信息存储在它所属的值中,而不是存储在代码中。

我猜580.55将被转换为58054。999999999999999999999999…,在这种情况下,int将把它四舍五入为58054。您可能需要编写自己的函数,通过某种舍入或阈值将金额转换为整数,以避免这种情况发生。

由于如下舍入错误,您确实不应该使用双精度值来表示货币


相反,你可以考虑使用积分值来表示货币量,以便精确地表示它们。要表示小数,可以使用与值

58055
存储
580.55
类似的技巧。不,相乘不会引入舍入错误 但并非所有值都可以用浮点数表示。
x、 55是其中之一)

十进制比双精度更精确。试试看

试试看

((int)(Math.Round(customerBatch.Amount * 100.0))).ToString()

处理浮点错误:参见本文:TL;DR:不要使用float或double进行货币计算。该值以货币值的形式来自SQL Server数据库。对象包装器类对这些值使用“double”,因此我无法更改金额的类型。在处理货币时,您应该尽可能使用十进制而不是浮点。@Sophtware:您应该在包装器类上引发一个错误,因为将货币值表示为double或float是一个错误。+1,文档甚至建议使用十进制进行财务/货币计算:忽略.Dump()方法。从LinqPad复制并粘贴。因此,您建议使用:((int)((decimal)customerBatch.Amount*100.0m)).ToString()@Sophtware您可以删除对intIt的强制转换,该值可能适用,但其他值则不适用。一旦您的“包装器”将SQL货币转换为双倍,则会造成损失。你必须去掉双精度。换句话说,计算机上的浮点数相乘确实会引入舍入错误。第一个舍入错误发生在580.55存储在580.54999999xxx的“双精度”中时。将其乘以100得到58054.999999xxx,其精度实际上并不比580.54999999xxx低。当然,浮点类型的乘法会引入舍入误差。将两个N位尾数相乘需要大约2N位来准确存储产品。您必须丢失大约N位才能将结果再次存储回同一类型。如果是这种情况,int将取整数部分,而不是四舍五入。那么像((int)(round(customerBatch.Amount*100.0)).ToString()这样的东西怎么样?是的,那可能会有用(我不熟悉C#,也不知道它内置了round函数)。你猜得太离谱了。58054.9999999... 不比580.55更准确地表示为浮点数。我的观点是数字580.55可能没有存储为580.55。打印出来时可以表示为580.55。如果它被存储为小于580.55的数字(不管它打印的是什么),它可能会通过转换为整数而向下舍入。