2

I know how to convert a float into it's binary representation using % 2 and / 2, but is there a shortcut or cleaner way of doing this? Is what I am doing even considered representing a float bitwise? Because I am supposed to be using bitwise comparison between two float numbers, but I'm not sure if that means using bitwise operations.

For example to obtain the binary representation for a number I'd store the resultant of a number like 10 % 2 into an array until the number reached 0 within a while loop and if the array were to be printed backwards it would represent the number in binary.

array[] = num % 2;
num = num / 2; 

What I did was use the method above for two float numbers, loaded them up with their own individual arrays, and compared them both through their arrays.

I have them set up in IEEE floating point format within their arrays as well.

EDIT: I have to compare two numbers of type float by using bitwise comparison and operations to see if one number is greater, less than, or if they are equal with the floats represented in biased exponent notation. The specifics are that it tests whether a floating point number number1 is less than, equal to or greater than another floating point number number2, by simply comparing their floating point representations bitwise by using bitwise comparisons from left to right, stopping as soon as the first differing bit is encountered.

Vso
  • 21
  • 1
  • 8
  • The commonly uses format for floating point on computers is the [IEEE floating point format](https://en.wikipedia.org/wiki/IEEE_floating_point). Doing a bitwise comparison between two such numbers simply makes no sense. – Some programmer dude Feb 19 '16 at 10:31
  • 4
    not too sure if you could get binary representation for *float* by `%2` or `/2`. – Ian Feb 19 '16 at 10:31
  • 2
    If you want to see the binary representation of a float, you can't just use `/ 2` and `% 2` because they will only give you information about the numeric interpretation of the number, rather than its bit-wise representation. To see its representation, you can put it in a `union` with an integer type of the same size (this is machine-dependent), or a `char` array of the same size (also machine-dependent, but you can use `sizeof` to get it), store to the `float` member, then access the other member to see what was stored. Also beware of big- vs. little-endian representation. – Tom Karzes Feb 19 '16 at 10:31
  • It's not clear which of two completely different things you're asking about. Do you want the internal bitwise representation of floating point numbers? Or do you want the numbers in binary? These are not the same at all because the internal bitwise representation for floating point number is floating point. For example, 2 and 16 are stored with the same mantissa and an exponent four greater. Dividing by two just moves a binary point. It won't shift out the bits. – David Schwartz Feb 19 '16 at 10:36
  • Is it correct that you just wish to do the bitwise comparison of two variables of type `float` in C? Because your idea is incorrect, and we could help you if you clarify that this is your goal. – RaidenF Feb 19 '16 at 10:42
  • @K.Gkinis yes I wish to do a bitwise comparison between two variables of type float. I can represent the float values in IEEE format, but I don't think what I am doing is considered bitwise comparison. – Vso Feb 19 '16 at 10:44
  • The answer below by rr- , should cover you. If you want to do it with bitwise operators, on the bit representation of the variable, you can just use them directly ( bitwise or: `|` bitwise and: `&` ). This will produce meaningless results though, due to their representation. If you want to compare them as numbers, but bitwise, you should compare their sign, then their expotent then their mantissa, separately. If you want me to explain how to do that, tell me! – RaidenF Feb 19 '16 at 10:49
  • @K.Gkinis The thing is I can represent a float in IEEE format using my method, but I fear this has nothing to do with bits. I would post the code, but it's far too confusing and lengthy. I basically loaded an array containing the IEEE format of a 32 bit float number, and if you were to print it out backwards it would print the sign 8bit exponent and 22bit mantissa. And having two arrays of numbers i'd compare them through a loop, but I am not using any bitwise operators, and I'm pretty sure I need to use them. I basically programmed my way around using bits. – Vso Feb 19 '16 at 10:55
  • The mantissa part is 23 bits, not 22. And no way you can get the binary representation with only /2 and *2. How about NaN and INF? – phuclv Feb 19 '16 at 10:56
  • @LưuVĩnhPhúc sorry I forgot the specifics it's been a long day, but no there is quite a lot of manipulations and coding along with that, I just wanted to provide a very small sample of what I am doing to see if it's even right. For those I would just put it under an if condition where if the exponent is all 1 it returns an error stating it's infinity and basically do the same for all the other conditions. – Vso Feb 19 '16 at 11:03
  • is there a reason you don't use operator ==? – user3528438 Feb 19 '16 at 11:23

3 Answers3

2

No, it won't. Dividing a float by 2 will result in half of the number like this:

#include <stdio.h>
int main(void)
{
    float x = 5.0f;
    float y = x / 2;
    printf("%f\n", y);
}

Result:

2.50000

see? It has nothing to do with bits.

Binary representation of floating numbers consists of mantissa, exponent and a sign bit, which means that unlike for normal integers, the tricks you've mentioned won't apply here. You can learn more about this by reading an article on Wikipedia on IEEE floating points.

To make sure two floats have exactly the same bit configurations, you could compare their content using memcmp which compares things byte-by-byte, with no additional casts/arithmetic/whatever:

#include <stdio.h>
int main(void)
{
    float x = 5.0f;
    float y = 4.99999999999999f; //gets rounded up to 5.0f
    float z = 4.9f;
    printf("%d\n", memcmp(&x, &y, sizeof(float)) == 0);
    printf("%d\n", memcmp(&x, &z, sizeof(float)) == 0);
}

...will print 1 and 0 respectively. You can also inspect the individual bits this way (e.g. by operating on a *(char*)&x.

rr-
  • 14,303
  • 6
  • 45
  • 67
  • 1
    `memcmp()` takes `const void *`, there's absolutely no point in casting to `char *`. Also better to use `sizeof x`, i.e. size of an object and not a type. – unwind Feb 19 '16 at 10:36
  • 1
    To be more precise, dividing a floating point number by two will simply reduce its exponent by one. – David Schwartz Feb 19 '16 at 10:36
  • Pardon my C++ :) Fixed. Regarding `sizeof x` - it's not obvious which operand to use (`sizeof x` or `sizeof y`) so I left it as it is. – rr- Feb 19 '16 at 10:37
  • Now how would I know if one was greater than the other? I see this can give me the condition to see if they are equal or not though. – Vso Feb 19 '16 at 11:09
1

This compares two IEEE 32-bit floats bit by bit, returning -1, 0, or 1, and also indicating the bit at which they differ. They can be compared as sign-and-magnitude numbers. The function float_comp below first compares them bit-by-bit as uint32_t and negates the comparison if they differ in the sign bit (bit 31).

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

static int float_comp(float f1, float f2, int *bit)
{
    const uint32_t *a, *b;
    int comp = 0;

    a = (const uint32_t *)(const void *)&f1;
    b = (const uint32_t *)(const void *)&f2;
    for (*bit = 31; *bit >= 0; (*bit)--) {
        if ((*a & (UINT32_C(1) << *bit))
             && !(*b & (UINT32_C(1) << *bit))) {
            comp = 1;
            break;
        }
        if (!(*a & (UINT32_C(1) << *bit))
             && (*b & (UINT32_C(1) << *bit))) {
            comp = -1;
            break;
        }
    }
    if (*bit == 31)
        comp = -comp;   /* sign and magnitude conversion */
    return comp;
}

int main(int argc, char **argv)
{
    float f1, f2;
    int comp, bit;

    if (argc != 3) {
        fprintf(stderr, "usage: %s: float1 float2\n", argv[0]);
        return 2;
    }
    f1 = strtof(argv[1], NULL);
    f2 = strtof(argv[2], NULL);
    comp = float_comp(f1, f2, &bit);
    if (comp == 0)
        printf("%.8g = %.8g\n", f1, f2);
    else if (comp < 0)
        printf("%.8g < %.8g (differ at bit %d)\n", f1, f2, bit);
    else
        printf("%.8g > %.8g (differ at bit %d)\n", f1, f2, bit);
    return 0;
}
Ian Abbott
  • 15,083
  • 19
  • 33
0

Doing what you said will not give you the bits of floating point representation. Instead use union to convert between float and integer representations and print bits as usual:

#include <stdio.h>
#include <stdint.h>

typedef union {
    uint32_t i;
    float f;
} float_conv_t;

void
int_to_bin_print(uint32_t number)
{
    char binaryNumber[33];
    int i;
    for (i = 31; i >= 0; --i)
    {
        binaryNumber[i] = (number & 1) ? '1' : '0';
        number >>= 1;
    }
    binaryNumber[32] = '\0';
    fprintf(stdout, "Number %s\n", binaryNumber);
}

int main(void) {
    float_conv_t f;
    f.f = 10.34;
    int_to_bin_print(f.i);
    f.f = -10.34;
    int_to_bin_print(f.i);
    f.f = 0.1;
    int_to_bin_print(f.i);
    f.f = 0.2;
    int_to_bin_print(f.i);
    return 0;
}

Output:

Number 01000001001001010111000010100100

Number 11000001001001010111000010100100

Number 00111101110011001100110011001101


My goal is to compare two floating point numbers by comparing their floating point representations bitwise.

Then you can compare raw memory using memcmp:

float f1 = 0.1;
float f2 = 0.2;
if (memcmp(&f1, &f2, sizeof(float)) == 0)
    // equal

SYNOPSIS #include

   int memcmp(const void *s1, const void *s2, size_t n);

DESCRIPTION The memcmp() function compares the first n bytes (each interpreted as unsigned char) of the memory areas s1 and s2.

RETURN VALUE The memcmp() function returns an integer less than, equal to, or greater than zero if the first n bytes of s1 is found, respectively, to be less than, to match, or be greater than the first n bytes of s2.

4pie0
  • 29,204
  • 9
  • 82
  • 118
  • But does this compare the bits from left to right essentially? Sorry I am just lost when it comes to bits. What I mean I guess is in the memory is 0.1 stored in IEEE format? And then memcmp would compare the two float numbers bit by bit? And if they happen to not be equal, how would you know which one was greater? – Vso Feb 19 '16 at 11:05
  • yes, memcmp compares byte by byte which translates to bits by bits, memcmp returns > 0 if the byte that differs has higher value in first argumnet and < 0 otherwise – 4pie0 Feb 19 '16 at 11:15
  • Ahhh I didn't read over the instructions well enough, biased exponent notation needed for comparison. – Vso Feb 19 '16 at 11:25
  • For the code you provided first how would I print out the bits without using stdout? Can I load it into an array and print it out instead or does that not work? – Vso Feb 20 '16 at 00:15
  • [The bias allows one to compare floating-point values directly using integer comparison of their bit representations](http://stackoverflow.com/q/19864749/995714). Now you need to get the bit representation of the values – phuclv Feb 20 '16 at 06:30