Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.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# 四舍五入_C#_.net - Fatal编程技术网

C# 四舍五入

C# 四舍五入,c#,.net,C#,.net,我有一个“科学应用”,在这个应用中,单个值在显示在UI中之前应该四舍五入。根据,由于“精度损失”Math.Round(Double,Int32)方法有时会出现“意外”行为,例如将2.135舍入到2.13,而不是2.14 据我所知,这个问题与“银行家取整”无关(例如,请参阅) 在应用程序中,显然有人选择在取整(即Math.Round((Decimal)mySingle,2))之前显式地将Single转换为Decimal,以调用Math.Round(Decimal,Int32)重载来解决这个问题。除

我有一个“科学应用”,在这个应用中,
单个
值在显示在UI中之前应该四舍五入。根据,由于“精度损失”
Math.Round(Double,Int32)
方法有时会出现“意外”行为,例如将2.135舍入到2.13,而不是2.14

据我所知,这个问题与“银行家取整”无关(例如,请参阅)

在应用程序中,显然有人选择在取整(即
Math.Round((Decimal)mySingle,2)
)之前显式地将
Single
转换为
Decimal
,以调用
Math.Round(Decimal,Int32)
重载来解决这个问题。除了可能出现的二进制到十进制转换问题外,如果
单个
值太小或太大而不适合
十进制
类型,此“解决方案”还可能导致抛出
溢出异常

如果转换失败,捕获这些错误以从
Math.Round(Double,Int32)
返回结果,我认为这不是完美的解决方案。重写应用程序也不会一直使用
Decimal


是否有一种或多或少“正确”的方法来处理这种情况,如果有,可能是什么?

我刚刚查看了文档,似乎有一个枚举可以传递到
Math.Round()
。如果您更改为
Math.Round(Double,Int32,middpointrounding.AwayFromZero)
您应该会得到所需的结果

编辑:仅使用这些数字进行测试。更改了号码和

    double abc = 2.335;
    Console.WriteLine(Math.Round(abc, 2, System.MidpointRounding.AwayFromZero));        
    abc = 2.345;
    Console.WriteLine(Math.Round(abc, 2, System.MidpointRounding.AwayFromZero));

    abc = 2.335;
    Console.WriteLine(Math.Round(abc, 2));      
    abc = 2.445;
    Console.WriteLine(Math.Round(abc, 2));
得到了这些结果

2.34
2.35
2.34
2.44
编辑2:我用的是你给的原始数字,它正在崩溃。我认为使用AwayFromZero可以解决双舍入问题(我认为它只适用于银行家舍入),但事实并非如此。如果您确实需要从舍入中获得所需的精度,您必须创建自己的函数,通过转换为double或其他方法来提供所需的精度,但我已经寻找了一段时间,但没有找到任何结果,我会回来查看您是否找到了解决方案

double abc = 2.135;
Console.WriteLine(Math.Round(abc, 2, System.MidpointRounding.AwayFromZero));        
abc = 2.145;
Console.WriteLine(Math.Round(abc, 2, System.MidpointRounding.AwayFromZero));

abc = 2.135;
Console.WriteLine(Math.Round(abc, 2));      
abc = 2.145;
Console.WriteLine(Math.Round(abc, 2));

2.13
2.15
2.13
2.14

我认为您现有的解决方案(使用Math.Round的
Decimal
版本)是正确的

潜在的问题是,您希望数字根据其以10为基数的表示形式进行舍入,但您将其存储为以2为基数的浮点数。所提供的2.135示例是基2表示与基10不完全匹配的边缘情况之一


要获得预期的舍入行为,必须将数字转换为以10为基数。最简单的方法就是您正在做的事情:临时将数字转换为一个
十进制
,时间足够长,可以调用
数学。舍入

,因为浮点以精度换取范围,所以十进制值2.135不能用二进制精确表示

[最接近的]二进制表示法类似于
0.1348876953125
decimal,因此舍入是正确的(如果直观上不明显的话)

你应该读戈德伯格的论文,()

摘要。浮点运算被许多人认为是一门深奥的学科。这相当令人惊讶,因为浮点在计算机系统中无处不在:几乎每种语言都有浮点数据类型;从个人电脑到超级计算机都有浮点加速器;大多数编译器会不时被要求编译浮点算法;实际上,每个操作系统都必须响应浮点异常,例如溢出。本文介绍了一个有关浮点运算的教程,它对计算机系统的设计者有着直接的影响。它从浮点表示和舍入误差的背景开始,继续讨论IEEE浮点标准,并以计算机系统构建者如何更好地支持浮点的示例结束


请提供一个可运行的代码示例,其中2.135轮到2.13轮?小数的范围比单个小数的范围大,所以不应该有overflow@ScottChamberlain提供的MSDN链接包含此类代码。可能是,如果您可以仅为trunc转换它们,则可以使用Math。Truncate:@aochagavia I get
System.OverflowException:值对于十进制而言太大或太小。在System.Decimal..ctor(单值)
。感谢您的贡献,但您可能没有花时间正确阅读我提供的链接。此外,我已经明确表示,我认为“银行取整”问题是一个不同的问题,并提供了足够的信息,您应该能够理解这意味着什么。对不起,我阅读了文档,它说,“在某些情况下,这一轮(双,中点取整)方法可能不会将中点值舍入为最接近的偶数整数”。我认为如果使用AwayFromZero,这将被忽略,但下面的示例表明,即使这样也不起作用。因此,您只能使用小数。但是当您将single转换为decimal时,不是也会发生同样的情况吗?值得注意的是,.NET decimal格式仍然没有存储真正的以10为基数的表示形式,因此如果在精度刻度的最末端重复添加/减去小数,您可能会遇到累加错误。它非常适合以有限的精度处理典型的base-10数学,但是,它将正确地复制“手动”计算,这些计算可以在base-10中以有限的小数进行。@Graham如果我理解正确,那么,是的,有一种舍入是在将一个单数转换为十进制时执行的。因此,2.134999999或其他任何东西被四舍五入到其十进制等价物2.135,然后被传递到Math.Round并转换为2.14。所以我不认为转换为十进制有帮助,因为在您的示例中,我希望2.1349四舍五入到2.13(s)