0

Both of the below expressions are True:

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

I realize that Math.Round returns a Double, but I can always use an Integer in the same context even with Option Strict On. So, are there situations in which one would want to use Math.Round(..., MidpointRounding.AwayFromZero) instead of the shorter CInt?

P.S. There is a question on the same topic (asked by me as well), but that question was badly asked and, as a result, the answers do not address the real question.

Community
  • 1
  • 1
AlwaysLearning
  • 7,257
  • 4
  • 33
  • 68

2 Answers2

1

In the example given the result is true, but if you change the numbers to 4.5 they are not.

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

CInt uses MidpointRounding.ToEven rounding. If a rounding mode is not provided for Math.Round MidpointRounding.ToEven is used.

The answer is to understand what each method does and to use the appropriate method.

dbasnett
  • 11,334
  • 2
  • 25
  • 33
  • So, would it be true to say that there is never a good reason to use `Math.Round(..., MidpointRounding.ToEven)` and not `CInt`? – AlwaysLearning Nov 19 '16 at 16:32
  • If you have two methods that do the SAME exact thing, what difference does it make? IF performance is an issue then pick the faster one. – dbasnett Nov 19 '16 at 22:56
0

CInt(Double) is compiled to implicit cast that calls the default Math.Round(Double) and converts the result to Integer, so the main reasons to use Math.Round(Double, MidpointRounding.AwayFromZero) instead of CInt(Double) would be

  • to use the MidpointRounding.AwayFromZero rounding instead of the default MidpointRounding.ToEven rounding
  • to avoid System.OverflowException when the result can't fit in Integer (Anything smaller than Integer.MinValue or larger than Integer.MaxValue such as Dim d = 2 ^ 31)
  • if CInt(1.5) in VB.Net is converted carelessly to (int)1.5 in C#, small rounding errors might occur. In VB.Net CInt(1.5) is 2, but in c# (int)1.5 is 1.

The CIL bytecode generated (in VS 2010 .NET 3.5) from

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

in ildasm.exe is:

  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

which shows that the 3 conversions compile to the same call to the default Math.Round(Double) and conv.ovf.i4 Integer conversion.

Slai
  • 22,144
  • 5
  • 45
  • 53
  • What would be an example when `CInt` throws, but `Math.Round` succeeds? – AlwaysLearning Nov 19 '16 at 16:35
  • Anything smaller than `Integer.MinValue` or larger than `Integer.MaxValue` such as `Dim d = 2 ^ 31`. `CInt(2 ^ 31)` will not even compile, but `CInt(2 ^ 31 - 1)` will. Just for reference, `Double.MaxValue` is about 299 times larger than `Integer.MaxValue` – Slai Nov 19 '16 at 21:03