2014-12-05 100 views
0

我试图截断C#中的一系列双精度值。无论使用什么舍入方法,以下值都会失败。这个值导致这两种方法失败的问题是什么?为什么即使Math.Round未能正确截断数字?可以使用什么方法来正确截断这些值?舍入到specfic数字失败,这个双精度值

值:

double value = 0.61740451388888251; 

方法1:

return Math.Round(value, digits); 

方法2:

double multiplier = Math.Pow(10, decimals) 
return Math.Round(value * multiplier)/multiplier; 

即使在VS观看无线失败ndow!

round

+1

浮点类型不能代表所有可能的值,这意味着这大概是0.62尽可能最接近。 – 2014-12-05 19:45:59

+1

为什么downvote?这是一个非常令人困惑的问题,绝不是初学者的问题。你不明白这个问题的前提吗? – 2014-12-05 19:46:54

+0

@JordiVermeulen - 'double'肯定可以正确表示0.62。 – 2014-12-05 19:47:37

回答

4

双是一个浮动二进制点类型。它们以二进制形式表示(如11010.00110)。当double以十进制表示时,它只是一个近似值,因为并非所有的二进制数都有十进制的精确表示。尝试例如此操作:

double d = 3.65d + 0.05d; 

它不会导致3.73.6999999999999997。这是因为变量包含最接近的可用double

您的情况也是如此。您的变量包含最接近的可用double

对于精确操作double/float不是最幸运的选择。 当您需要快速性能或者您想要在更大范围的数字上操作时,使用double/float,但不需要高精度。例如,它是物理计算的完美类型。 精确的小数运算使用,以及decimal

这里是关于float/decimal的文章:http://csharpindepth.com/Articles/General/FloatingPoint.aspx

0

我认为你是对一个双精度浮点(64位)的二进制极限跑起来。从http://en.wikipedia.org/wiki/Double-precision_floating-point_format,双重只给出15-17个有效数字。

+0

为什么'Math.Round'无法正确截断数字?什么方法可以用来代替? – 2014-12-05 19:58:37

+0

你只是想四舍五入到小数点后两位? – ryanyuyu 2014-12-05 20:02:27

+0

由于您使用的是C#,因此可以使用Decimal类。 http://msdn.microsoft.com/en-us/library/System.Decimal(v=vs.110).aspx – ryanyuyu 2014-12-05 20:07:18

3

根据这个在线工具,它使双打的二进制表示,以0.62最接近的两个双值:

6.19999999999999995559107901499E-10x3FE3D70A3D70A3D7 link

6.20000000000000106581410364015E-10x3FE3D70A3D70A3D8 link

我我不确定为什么这些都不能完全符合你的价值,但正如其他人说的那样,这可能是一个浮点表示问题。

3

如果您需要更准确地表示数字,您可能必须使用decimal类型,该类型具有更高的精度但范围更小(通常用于财务计算)。关于何时使用每个这里

更多信息:https://stackoverflow.com/a/618596/1373170