c# vs python float 舍入差异
c# vs python float rounding differences
我正在 python 中开发一个应用程序,其中一些部分是用 c# 编写的(为了加快速度),我很困惑为什么 c# 浮点舍入的行为类似于 "opposite" 到 python 当使用 "round" 函数和字符串浮点格式化函数时,这里有一个例子:
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# 之间的行为看似 "reversed" 吗?有没有办法将 "double" 浮点值四舍五入为 N 位十进制数字,以在 Python 和 C# 之间产生保证相同的字符串输出?
参考Banker's Rounding。
这是一个有意的实现细节。
如果您希望保留 'always round 0.5 up' 方法或您想要的任何其他舍入方式,您可以通过执行以下操作来实现:
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')
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。
这是由于您调用的两个方法的中点分辨率所致。
Python的round(number[, ndigits])
Return the floating point value number rounded to ndigits
digits after the decimal point. If ndigits
is omitted, it defaults to zero. The result is a floating point number. Values are rounded to the closest multiple of 10 to the power minus ndigits
; if two multiples are equally close, rounding is done away from 0
(so, for example, round(0.5)
is 1.0
and round(-0.5)
is -1.0
).
Rounds a double-precision floating-point value to a specified number of fractional digits, and rounds midpoint values to the nearest even number.
换句话说:
- Python 从零舍入(
6.25
变为 6.3
因为 6.3
比 6.2
更远离 0
)
- C# 舍入到最接近的偶数,因此
6.25
变为 6.2
因为 6.2
是最接近的偶数。
您可以通过使用 Math.Round
的重载之一来解决此问题,它采用 MidpointRounding
enum value 例如 Round(double, int, MidpointRounding)
,例如:
Math.Round(6.25, 1, MidpointRounding.AwayFromZero);
这将与 Python 舍入做同样的事情。
我正在 python 中开发一个应用程序,其中一些部分是用 c# 编写的(为了加快速度),我很困惑为什么 c# 浮点舍入的行为类似于 "opposite" 到 python 当使用 "round" 函数和字符串浮点格式化函数时,这里有一个例子:
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# 之间的行为看似 "reversed" 吗?有没有办法将 "double" 浮点值四舍五入为 N 位十进制数字,以在 Python 和 C# 之间产生保证相同的字符串输出?
参考Banker's Rounding。
这是一个有意的实现细节。
如果您希望保留 'always round 0.5 up' 方法或您想要的任何其他舍入方式,您可以通过执行以下操作来实现:
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')
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。
这是由于您调用的两个方法的中点分辨率所致。
Python的round(number[, ndigits])
Return the floating point value number rounded to
ndigits
digits after the decimal point. Ifndigits
is omitted, it defaults to zero. The result is a floating point number. Values are rounded to the closest multiple of 10 to the power minusndigits
; if two multiples are equally close, rounding is done away from0
(so, for example,round(0.5)
is1.0
andround(-0.5)
is-1.0
).
Rounds a double-precision floating-point value to a specified number of fractional digits, and rounds midpoint values to the nearest even number.
换句话说:
- Python 从零舍入(
6.25
变为6.3
因为6.3
比6.2
更远离0
) - C# 舍入到最接近的偶数,因此
6.25
变为6.2
因为6.2
是最接近的偶数。
您可以通过使用 Math.Round
的重载之一来解决此问题,它采用 MidpointRounding
enum value 例如 Round(double, int, MidpointRounding)
,例如:
Math.Round(6.25, 1, MidpointRounding.AwayFromZero);
这将与 Python 舍入做同样的事情。