c#vs python float舍入差异

时间:2019-01-03 18:42:13

标签: c# python floating-point rounding

我正在用python开发应用程序,其中一些部分用c#编写(以加快速度),而我困惑为什么在使用“ round”函数和字符串浮点时,c#浮点舍入与python表现为“相反”格式化功能,下面是一个示例:

Python(2.7)

>>> round(6.25, 1)
6.3
>>> "%.1f"%6.25
6.2

C#

>>> Math.Round(6.25,1)
6.2
>>> (6.25).ToString("F1")
6.3

有人知道为什么Python与C#之间的行为看起来“相反”吗?有没有办法将“双”浮点值舍入为N个十进制数字,以在Python和C#之间产生保证相同的字符串输出?

3 个答案:

答案 0 :(得分:3)

这是由于您正在调用的两个方法的中点分辨率。

Python的round(number[, ndigits])

  

返回小数点后四舍五入为ndigits位的浮点数。如果省略ndigits,则默认为零。结果是一个浮点数。值四舍五入到与幂减ndigits相乘的10的最接近倍数;如果两个倍数相等地接近,则四舍五入要远离0(例如,round(0.5)1.0,而round(-0.5)-1.0)。

C#的Math.Round(double, int)

  

将双精度浮点值四舍五入为指定数量的小数位数,并将中点值四舍五入为最接近的偶数。

换句话说:

  • Python四舍五入为零(6.25变为6.3,因为6.306.2更远)
  • C#四舍五入到最接近的偶数,因此6.25成为6.2,因为6.2是最接近的偶数。

您可以通过使用MidpointRounding enum value之类的Math.Round重载之一来解决此问题,例如Round(double, int, MidpointRounding) ,例如:

Math.Round(6.25, 1,  MidpointRounding.AwayFromZero);

与Python取整功能相同。

答案 1 :(得分:2)

引用Banker's Rounding
它是有目的的实现细节。 如果您希望保留“始终向上舍入0.5向上”方法或您希望使用的任何其他舍入方法,则可以执行以下操作:

import decimal
#The rounding you are looking for
decimal.Decimal('3.5').quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_UP)
>>> Decimal('4')
decimal.Decimal('2.5').quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_UP)
>>> Decimal('3')


#Other kinds of rounding
decimal.Decimal('2.5').quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_EVEN)
>>> Decimal('2')

decimal.Decimal('3.5').quantize(decimal.Decimal('1'), rounding=decimal.ROUND_HALF_DOWN)
>>> Decimal('3')

答案 2 :(得分:1)

Math.Round默认使用银行家的四舍五入,四舍五入到最接近的偶数值(例如,如您所见,Math.Round(6.25,1)-> 6.2,以及Math.Round(6.35,1)-> 6.4)。要更改此设置,请使用MidpointRounding值,例如Math.Round(6.25, 1, MidpointRounding.AwayFromZero)

对于另一个问题,double.ToString()会导致舍入。有关此问题的解决方法,请参见C# Double - ToString() formatting with two decimal places but no rounding