Assigning binary fraction to float variable in C

132 views Asked by At

I am trying to do something like as below

#include <stdio.h>

int main() {
    float a = 0b00000100;
    float b = 0b0.0110; // this line is not working
    printf("The value of first float is = %f\n", a * 15);
    printf("The value of second float is = %f\n", b);
    return 0;
}

My only goal here is to assign b with the fractional binary number which is 0.0110 and should result in 0.375. Anyone any idea?

3

There are 3 answers

0
Shon_Shon On

I quickly made this code:

#include<stdio.h>
#include<string.h>

float binary_f(char fraction[]){
  char *pointp; //pointer to the point
  long integer=strtol(fraction, &pointp, 2); //Gives the integer and the pointer to the point, at the same time!
  int point=(int)(pointp-fraction);
  
  long div = 2;
  int lenght=strlen(fraction);
  float result=0;
  
  for (int i=point+1;i<lenght;i++){
    if (fraction[i]=='1'){
      result+=(float)1/div; 
    }
    div <<= 1; //Multiply the divisor by 2
  }
  return result+(float)integer;
}

int main() {
  char fractionary[]="10.001";
  float a=binary_f(fractionary);
  printf("%f",a);
  return 0;
}

Prints:

2.125000

As you may notice, it isn't really robust, but it does the job for it's expected parameters.

0
ad absurdum On

Standard C does not have binary floating constants, and note that binary integer constants were only recently added to the language with C23; previously binary integer constants like 0b00000100 were only available as implementation-specific extensions.

But C has had hexadecimal floating constants since C99. These are useful for working with binary representations. Each of the 16 hexadecimal digits corresponds to a four-digit binary sequence; if you learn these you can quickly write down the hexadecimal equivalent of a binary representation.

Binary Hexadecimal Binary Hexadecimal
0000 0 1000 8
0001 1 1001 9
0010 2 1010 A
0011 3 1011 B
0100 4 1100 C
0101 5 1101 D
0110 6 1110 E
0111 7 1111 F

The format of a hexadecimal floating constant in C is a hexadecimal prefix (0x or 0X) followed by a hexadecimal fractional constant (e.g., ABC.DEF) followed by a (mandatory) binary exponent part. The binary exponent part must be prefixed by either p or P (e.g., p-3). Note that the binary exponent is expressed in powers of 2 instead of powers of 10.

Hexadecimal floating constants have type double by default. If a hexadecimal floating constant is suffixed by f or F it has type float, and if suffixed by l or L it has type long double.

Referencing the table above the OP desired 0b0.0110 can be written in hexadecimal as 0x0.6p0 since 0110 is equivalent to the hexadecimal digit 6. An exponent is required, and p0 indicates that the significand should not be scaled.

Here is an example in code:

#include <stdio.h>

int main(void) {
    // binary float: 0.0110
    double b = 0x0.6p0;

    // binary float: 1101 1110 1010 1101 . 1011 1110 1110 1111
    // hex float:     D    E    A    D   .  B    E    E    F
    double dead_beef = 0xDEAD.BEEFp0;
    double d_eadbeef = 0xD.EADBEEFp12; // `p12` moves the "decimal" point 12 binary digits to the right

    printf("b = %f\n", b);
    printf("dead_beef = %f\n", dead_beef);
    printf("d_eadbeef = %f\n", d_eadbeef);
}
> ./fc
b = 0.375000
dead_beef = 57005.745834
d_eadbeef = 57005.745834
0
chqrlie On

The upcoming C23 Standard introduces the 0b0110 syntax for integers, but not for floating point values.

Instead of float b = 0b0.0110; you could write:

float b = 0b0110 / 16.F;

Or more with the explicit number of fractional bits:

float b = 0b0110 * 0x1p-4F;

And for older C99 compilers:

float b = 0x6p-4F;