David Klempfner
David Klempfner

Reputation: 9870

BitConverter.GetBytes() showing incorrect value?

I'm trying to look at how a System.Single value is represented in memory.

From what I've read, System.Single is represented like this:

1 sign bit (s), 23 bit fractional significand (f) and a 8 bit biased exponent (e).

(-1)^s * 1.f * 2^(e-127)

In the case of 16777216 , s = 0, f = 00000000000000000000000 (23 zeros), e = 151 = 10010111

ie. 1.00000000000000000000000 * 2^24

In memory, I'd expect it to look like this (sign bit, fractional significand, biased exponent):

 0 00000000000000000000000 10010111

Or in bytes:

00000000 00000000 00000000 10010111

But instead it's giving me this:

00000000 00000000 10000000 01001011

Looks like the last bit is missing from the biased exponent, and a random 1 at the start of the 3rd byte, why is this?

I was able to find the right exponent by reversing the bits in each byte:

00000000 00000000 00000001 11010010

Taking the last 9 bits and reversing those again:

00000000 00000000 0000000 010010111

This is now equal to what I'd expect, but what is with this strange order?

What format is this binary number stored in?

Here's my code:

using System;
using System.Linq;

namespace SinglePrecision
{
    class Program
    {
        static void Main(string[] args)
        {
            Single a = 16777216;            
            byte[] aBytes = BitConverter.GetBytes(a);
            string s = string.Join(" ", aBytes.Select(x => Convert.ToString(x, 2).PadLeft(8, '0')));
            //s = 00000000 00000000 10000000 01001011
        }
    }
}

Upvotes: 0

Views: 604

Answers (1)

GSerg
GSerg

Reputation: 78155

First, you got the order of the parts wrong. It is sign bit s, then exponent e, then fraction f, so your binary representation, which you otherwise calculated correctly, would be

0 10010111 00000000000000000000000
s e        f

These bits are stored in 4 continuous bytes of memory:

01001011 10000000 00000000 00000000
se        f
byte1    byte2    byte3    byte4

but because your system is little-endian, they are stored in reverse order:

00000000 00000000 10000000 01001011
byte4    byte3    byte2    byte1

Endiannes reverses the order of bytes, but it does not reverse the order of bits within a byte.

The rightmost byte is the first logical byte of the float value, and its leftmost bit is the sign bit, which is 0.
The second from the right byte is the second logical byte, and its lefmost bit is the last bit of your exponent.

Upvotes: 2

Related Questions