Ankit Shah
Ankit Shah

Reputation: 1335

How does type casting work from double to byte

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

Answers (3)

Mong Zhu
Mong Zhu

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

Prasad Telkikar
Prasad Telkikar

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 and 1111 1111 (8-bit binary data) values can be defined as Min and Max value to byte variable respectively, so in integer it turns into 0 and 255

Upvotes: 4

Sweeper
Sweeper

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 or double 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

Related Questions