Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

confusion with result of Ushort

Tags:

c#

consider the following code :

ushort a = 60000;
a = (ushort)(a * a / a);
Console.WriteLine("A = " + a);  

//This prints 53954. Why??

and

ushort a = 40000;
a = (ushort)(a * a / a);
Console.WriteLine("a = " + a.ToString());

//This prints 40000. how??

any help appreciable ...

like image 611
Milan Mendpara Avatar asked Mar 05 '12 08:03

Milan Mendpara


2 Answers

Because 60000^2 is 3600000000 but the biggest number an int can hold is 2,147,483,647, so it starts over from -2,147,483,648.

A ushort can hold 65,535 and then starts over from 0:

For instance, this prints 0:

ushort myShort = 65535;
myShort++;
Console.WriteLine(myShort); //0

It's easier to see this if you break it into steps:

var B = A * A;

That actually exceeds the capacity of an int32, so it starts from -2,147,483,648 thus b equals -694967296 Then when you split B/A you get: -11582 which, when cast into a ushort becomes 53954.

ushort A = 60000;
var B = A * A; //-694967296
var C = B / A; //-11582
ushort D = (ushort)(C); //53954

The reason that 40000 works is that it does not exceed the capacity of an int32.

ushort A = 40000;
var B = A * A; //1600000000
var C = B / A; //40000
ushort D = (ushort)(C); //40000

uint can hold 60000^2 though, so this works:

ushort A = 60000;
var B = (uint)A * A; //3600000000
var C = B / A; //60000
ushort D = (ushort)(C); //60000

The reason that casting C to ushort yeilds 53954 is because the bytes of C is:

96
234
0
0

And the bytes of D is:

96
234

So they hold the same backing bytes, that's why you get 53954 and -11582

like image 159
Oskar Kjellin Avatar answered Sep 28 '22 20:09

Oskar Kjellin


Because it's equivalent to

A * A = -694967296 because the result ends up as an int, and overflow on the short gives a bit pattern that yields this negative result. Ultimately 60000 * 60000 can't be stored in a ushort. Add a watch in debug mode and you'll see this.

Then you have

-694967296 / 60000 - which yields -11582 as an int, but when cast to a ushort yields 53954 - again because of the underlying bit pattern.

Really, this code would need to be in a checked block because it's for this very reason that overflow errors cause massive issues.

like image 27
Andras Zoltan Avatar answered Sep 28 '22 18:09

Andras Zoltan