3

I ran a program in .Net 3.5 using C# which works fine

try
{
    int i = 2147483647;

    Console.WriteLine((i * 100 / i).ToString());

    Console.ReadLine();
}
catch (Exception)
{                
    throw;
}

When I run this program in C#, I don't get an exception (it outputs "0"). But when I run this program in VB.Net it results in "Arithmetic operation resulted in an overflow" exception

Try
    Dim i As Integer = 2147483647

    Console.WriteLine((i * 100 / i).ToString())

    Console.ReadLine()
Catch ex As Exception
    Throw
End Try

Why the different behavior between these two languages?

5
  • 3
    Maybe because VB.NET does overflow checking by default whereas C# doesn't? Commented Jul 6, 2013 at 4:15
  • 3
    BTW, nothing about BODMAS/PEMDAS implies that the answer should be 0 - this is a result of how C# is performing the overflow. In this case, (i * 100) = -100. Commented Jul 6, 2013 at 4:27
  • @MichaelBray: My interpretation was that this was a question about (i * 100) / i vs. i * (100 / i)... Commented Jul 6, 2013 at 4:33
  • @OliCharlesworth: I agree - I've edited the question to remove the references to BODMAS/PEMDAS. Nikhil, I also removed the images you included, because they didn't really provide any additional value that couldn't be simply described, and they just made the question hard to read. Commented Jul 6, 2013 at 4:44
  • (i * 100) / i is just 100. Commented Jul 6, 2013 at 5:28

3 Answers 3

5

Perhaps looking at the IL will clarify... Simplifying your code a bit:

C#:

int i = 2147483647;
int v = (i * 100 / i);

generates the following IL:

IL_0001:  ldc.i4      FF FF FF 7F 
IL_0006:  stloc.0     // i
IL_0007:  ldloc.0     // i
IL_0008:  ldc.i4.s    64 
IL_000A:  mul         
IL_000B:  ldloc.0     // i
IL_000C:  div         
IL_000D:  stloc.1     // v

while the VB version:

Dim i As Integer = 2147483647
Dim v As Integer
v = i * 100 / i

generates this IL, slightly different:

IL_0001:  ldc.i4      FF FF FF 7F 
IL_0006:  stloc.0     // i
IL_0007:  ldloc.0     // i
IL_0008:  ldc.i4.s    64 
IL_000A:  mul.ovf     
IL_000B:  conv.r8     
IL_000C:  ldloc.0     // i
IL_000D:  conv.r8     
IL_000E:  div         
IL_000F:  call        System.Math.Round
IL_0014:  conv.ovf.i4 
IL_0015:  stloc.1     // v

As you can see, VB is calling mul.ovf, which is "multiply, and check for overflow", and C# is calling mul which does not check for overflow.

Perhaps it doesn't answer your question as to why C# does it one way and VB the other, but at least it answers why it is happening. :)

Edit: see the answer by aquinas to get the "why".

Sign up to request clarification or add additional context in comments.

Comments

1

Try changing your program to this:

try {
    checked {
        int i = 2147483647;
        Console.WriteLine((i * 100 / i).ToString());
        Console.ReadLine();
    }
}
catch (Exception) {
    throw;
}

C# doesn't automatically perform arithmetic checking by default. However, if you go to project properties...Build Tab..Advanced..."[X] Check For Arithmetic overflow/underflow" then you will get the same behavior as VB.NET by default.

1 Comment

Yup - I confirmed that the IL output (see my response) does indeed switch to using mul.ovf instead of mul inside the checked block.
0

The output is different because the VB code you posted is not equivalent to the C# code. The correct conversion is:

Console.WriteLine((i * 100 \ i).ToString())

Note that C# performs integer (truncating) division on integers, while in VB you have to use the integer division operator '\' to do the same integer division.

(update: even when using the correctly converted integer division operator, I also get the same exception in my test, so obviously it's not just about the operator).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.