1

TL;DR Why does the (int)Math.Pow(2,32) return 0 on Mono and Int32.MinValue on .NET ?


While testing my .NET-written code on Mono I've stumbled upon the following line:

var i = X / ( (int)Math.Pow(2,32) ); well that line doesn't make much sense of course and I've already changed it to long.

I was however curious why didn't my code throw DivideByZeroException on .NET so I've checked the return value of that expression on both Mono and .NET

Can anyone please explain me the results?

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
migajek
  • 8,524
  • 15
  • 77
  • 116
  • 2
    The `Math.Pow` is a distraction. Your real question is why does `(int)(((double)Int32.MaxValue) + 1)` equal `Int32.MinValue` on .NET and 0 on mono. – Scott Chamberlain Feb 10 '15 at 23:03
  • possible duplicate of [No overflow exception for int in C#?](http://stackoverflow.com/questions/2056445/no-overflow-exception-for-int-in-c) – ps2goat Feb 10 '15 at 23:05
  • I voted as duplicate for the question on overflow. I'm not sure of the internals for mono, but C# doesn't throw overflow exceptions by default. http://stackoverflow.com/questions/2056445/no-overflow-exception-for-int-in-c – ps2goat Feb 10 '15 at 23:06
  • 4
    Doesn't seem like a duplicate of that to me. This isn't asking why no exception is thrown; it's asking why the unchecked result is different in Mono from .NET. As for that, IMHO the question is academic; the documentation promises only that ["the result is an unspecified value of the destination type"](https://msdn.microsoft.com/en-us/library/yht2cx7b.aspx), so each platform is free to do whatever it wants. – Peter Duniho Feb 10 '15 at 23:08
  • @ps2goat: `DivideByZeroException` is not an overflow exception. – Erti-Chris Eelmaa Feb 10 '15 at 23:08
  • Guys I believe it's not about overflow exceptions as the operation is called in "unchecked" context (default) so no exception is expected behavior – migajek Feb 10 '15 at 23:09
  • @ChrisEelmaa, sorry, I misspoke. .NET does not evaluate to zero, so you aren't dividing by zero. – ps2goat Feb 10 '15 at 23:09
  • @ps2goat: he knows that. He wants to know why .NET doesn't not evaluate to zero. – Peter Duniho Feb 10 '15 at 23:09
  • 1
    Are you sure? SO `var max = Int32.MaxValue; var assertion = max + 1 == Int32.MinValue;` Assertion is false in Mono. That sounds like it's out of whack with the C# spec. – Nathan Cooper Feb 10 '15 at 23:11
  • It almost looks like once overflow occurs, the value is set to `Int32.MinValue` – ps2goat Feb 10 '15 at 23:13
  • @NathanCooper, I agree. If Mono is supposed to copy .NET, Mono should be the one answering questions. – ps2goat Feb 10 '15 at 23:14
  • @NathanCooper No, that's absolutely not what Mono does. Try it. `assertion` will be true. (I did try it.) What you have is different from what's in the question, and what's in the question does not have a well-defined result in C#, as pointed out by Peter Duniho. –  Feb 10 '15 at 23:15
  • @hvd. Yep, just read Peter Duniho's comment. Of course it's to do with the casting. I had no idea it would be unspecified. Interesting. I would like to see the internal implementations, there must be a reason. – Nathan Cooper Feb 10 '15 at 23:19
  • I think @PeterDuniho should make that the answer. – Nathan Cooper Feb 10 '15 at 23:20
  • Maybe you want to test with mono master: https://bugzilla.xamarin.com/show_bug.cgi?id=26219 – David Karlaš Feb 11 '15 at 10:18
  • There can be hardware differences as well: https://bugzilla.xamarin.com/show_bug.cgi?id=26213#c3 – Rolf Bjarne Kvinge Feb 11 '15 at 13:08

2 Answers2

5

IMHO the question is academic; the documentation promises only that "the result is an unspecified value of the destination type", so each platform is free to do whatever it wants.

One should be very careful when casting results that might overflow. If there is a possibility of that, and it's important to get a specific result instead of whatever arbitrary implementation a given platform has provided, one should use the checked keyword and catch any OverflowException that might occur, handling it with whatever explicit behavior is desired.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
2

"the result is an unspecified value of the destination type". I thought it would be interesting to see what's actually happening in the .NET implementation.

It's to do with the OpCodes.Conv_I4 Field in IL: " Conversion from floating-point numbers to integer values truncates the number toward zero. When converting from a float64 to a float32, precision can be lost. If value is too large to fit in a float32 (F), positive infinity (if value is positive) or negative infinity (if value is negative) is returned. If overflow occurs converting one integer type to another, the high order bits are truncated" It does once again say overflow is unspecified however.

Nathan Cooper
  • 6,262
  • 4
  • 36
  • 75