Reading a Binary Fraction

As an example of how a binary values can hold fractions, I’ve concocted a simple real number format: An 8-bit value with 4 bits representing the whole number portion and 4 bits representing the fractional portion. Here’s how it looks:

Figure 1. Interpreting an 8-bit real number.

Figure 1. Interpreting an 8-bit real number.

In Figure 1, you see the binary value 0xC5, which when read as an unsigned char would be the value 197. In this interpretation, however, a decimal point lurks between the 4th and 5th bits in the value. Bits to the left represent positive powers of 2; bits to the right represent negative values.

Performing the math from Figure 1, you get bits representing values 8.0 and 4.0, so 12 is set as the whole number portion. To the right you get bits representing values 0.25 (¼) and 0.0625 (1/16), for a total of 0.3125 or 5/16. The complete value is 12.3125 or 125/16.

Bits are just bits, however, so what really matters is how your code interprets them. The value could be 197, or -59 for a signed char value, or the character Å. In this interpretation, however, it’s the real number 12.3125. To get to that result, you write code that properly interprets the 8-bit real number.

The following code shows how to make such a calculation. It takes the value 0xC5 and processes the bits in that unsigned char to generate a real number as output:

#include 

int main()
{
    float twos = 8;
    float result = 0;
    unsigned char binary = 0xC5;
    int x;

    printf("Binary value 0x%X is ",binary);
    for(x=0;x<8;x++)
    {
        if( binary & 0x80)
            result += twos;
        binary <<= 1;
        twos /= 2;
    }
    printf("%.4f\n",result);

    return(0);
}

The value of float variable twos is set to 8 at Line 5. That’s the power of 2 equal to the far-left bit in the code’s 4:4 real number format, shown in Figure 1.

Variable binary holds the sample value, 0xC5, which is the same value used in Figure 1.

The for loop at Line 11 processes all 8 bits of value binary. Each bit is examined (Line 13) and the appropriate power of 2 is assigned to variable result if the bit is set.

In Line 15, the value of variable binary is shifted left. That way each bit in the value is examined individually. Variable twos is cut in half in Line 16. As a float, its value is reduced from 8 to 4 to 2 to 1 and then to 0.5 or ½, and then to 0.25 or ¼, and so on. These values match the bit positions stored in variable binary as it continues to shift left.

Here is the code’s output:

Binary value 0xC5 is 12.3125

You could modify the code to hold larger and more precise values: A short int holds 16-bits, an int 32 bits, and a long 64 bits. You must keep the decimal place consistent with whatever size binary value you choose.

The beauty of all this binary nonsense is that the math still works: If you add or subtract the real number interpretations of binary values, the results calculate as you would expect.

Leave a Reply