Math.Round(...,MidpointRounding.AwayFromZero)在什么情况下比CInt更可取?

时间:2016-11-18 11:27:57

标签: vb.net

以下两个表达式均为True

CInt(3.5) = Math.Round(3.5, MidpointRounding.AwayFromZero)
CInt(-3.5) = Math.Round(-3.5, MidpointRounding.AwayFromZero)

我意识到Math.Round返回Double,但即使使用Integer,我也可以在相同的上下文中使用Option Strict On。那么,是否有人希望使用Math.Round(..., MidpointRounding.AwayFromZero)而不是较短的CInt

P.S。同一主题上有一个question(我也问过),但问题很严重,因此,答案并没有解决真正的问题。

2 个答案:

答案 0 :(得分:1)

在给出的示例中,结果为true,但如果将数字更改为4.5,则不是。

CInt(4.5) = Math.Round(4.5, MidpointRounding.AwayFromZero) 'False

CInt使用MidpointRounding.ToEven舍入。如果没有为Math.Round提供舍入模式,则使用MidpointRounding.ToEven。

答案是了解每种方法的作用并使用适当的方法。

答案 1 :(得分:0)

CInt(Double)被编译为隐式强制转换,调用默认的Math.Round(Double)并将结果转换为Integer,因此使用Math.Round(Double, MidpointRounding.AwayFromZero)代替CInt(Double)的主要原因将是

  • 使用MidpointRounding.AwayFromZero四舍五入而不是默认的MidpointRounding.ToEven四舍五入
  • 如果结果不适合System.OverflowException(任何小于Integer或大于Integer.MinValue的内容,例如Integer.MaxValue),请
  • 以避免Dim d = 2 ^ 31
  • 如果VB.Net中的CInt(1.5)在C#中不小心转换为(int)1.5,则可能会发生小的舍入错误。在VB.Net中,CInt(1.5)为2,但在c#(int)1.5中为1。

生成的CIL字节码(在VS 2010 .NET 3.5中)
Dim d As Double = 2.5

Dim i1 As Integer = CInt(d)             ' 2

Dim i2 As Integer = CType(d, Integer)   ' 2

Dim i3 As Integer = d                   ' 2

Dim d2 = Int(d)                         ' 2.0
ildasm.exe中的

是:

  IL_000f:  ldc.r8     2.5
  IL_0018:  stloc.0

  IL_0019:  ldloc.0
  IL_001a:  call       float64 [mscorlib]System.Math::Round(float64)
  IL_001f:  conv.ovf.i4
  IL_0020:  stloc.2

  IL_0021:  ldloc.0
  IL_0022:  call       float64 [mscorlib]System.Math::Round(float64)
  IL_0027:  conv.ovf.i4
  IL_0028:  stloc.3

  IL_0029:  ldloc.0
  IL_002a:  call       float64 [mscorlib]System.Math::Round(float64)
  IL_002f:  conv.ovf.i4
  IL_0030:  stloc.s    i3

  IL_0032:  ldloc.0
  IL_0033:  call       float64 [Microsoft.VisualBasic]Microsoft.VisualBasic.Conversion::Int(float64)
  IL_0038:  stloc.1

表明3次转换编译为默认Math.Round(Double)conv.ovf.i4整数转换的同一次调用。