Reputation: 1335
I have a code where type casting returns a value much different from the larger value.
static void Main(string[] args)
{
double a = 345.09;
byte c = (byte) a;
Console.WriteLine(c);
Console.ReadLine();
}
This returns the value 89
. What is the reason behind it?
Upvotes: 7
Views: 1026
Reputation: 23732
what happens is that only the last 8 bits are taken when you cast the number. Let me explain with an example using ints. I use int for simplicity, because if you cast double
to a non-float number representation than the decimal places are discarded anyway.
First we look at the binary representation of the number 345:
string binaryInt = Convert.ToString(345, 2);
Console.WriteLine(binaryInt);
The output is :
1 0101 1001
When we now take only the last 8 bits, which is the size of a byte
type:
string eightLastBits = binaryInt.Substring(binaryInt.Length-8);
Console.WriteLine(eightLastBits);
We get:
0101 1001
If we convert this to byte
again you will see that the result is 89:
byte backAgain = Convert.ToByte(eightLastBits, 2);
Console.WriteLine(backAgain);
Output:
89
EDIT:
As pointed out by InBetween the int example is the real deal and what really happens during casting.
Looking at the implementation of the conversion of double to byte:
/// <internalonly/>
byte IConvertible.ToByte(IFormatProvider provider) {
return Convert.ToByte(m_value);
}
If we look at the Convert.ToByte method implementation: we see that the double if first converted to an integer:
public static byte ToByte(double value) {
return ToByte(ToInt32(value));
}
Upvotes: 12
Reputation: 16049
Range of byte starts from 0 to 255, you are getting result as 89 because it starts counting again from 0 once it goes beyond 255. i.e
byte c = (byte) a; //345 - 255 (consider `0` as well)
Console.WriteLine(c); // i.e. 89
The reason behind the range of byte:
byte
stores 8-bit data.0000 0000
and1111 1111
(8-bit binary data) values can be defined asMin
andMax
value tobyte
variable respectively, so in integer it turns into0
and255
Upvotes: 4
Reputation: 271685
Note that this is one of the few cases where the result isn't specified.
From the language spec, omitting the irrelevant cases
For a conversion from
float
ordouble
to an integral type, the processing depends on the overflow checking context (The checked and unchecked operators) in which the conversion takes place:In an unchecked context, the conversion always succeeds, and proceeds as follows.
If the value of the operand is NaN or infinite, [...]
Otherwise, the source operand is rounded towards zero to the nearest integral value. If this integral value is within the range of the destination type, [...]
Otherwise, the result of the conversion is an unspecified value of the destination type
Presumably, the implementation simply stripped off the higher bits after converting to the nearest integral value, leaving just the least significant 8 bits, since that's likely the most convenient thing to do at that point. But do note that according to this spec, 0
is just as a valid value as 89
is, for this conversion.
Upvotes: 2