Float to Binary in C - c

I am asked to convert a float number into a 32 bit unsigned integer. I then have to check if all the bits are zero but I am having trouble with this. Sorry I am new to C
This is what I am doing
float number = 12.5;
// copying number into a 32-bit unsigned int
unsigned int val_number = *((unsigned int*) &number);
At this point I'm very confused on how to check if all bits are zero.
I think I need to loop through all the bits but I don't know how to do that.

To copy the bytes of a 32-bit float to an integer, best to copy to an integer type that is certainly 32-bit. unsigned may be less, same or more than 32-bits.
#include <inttypes.h>
float number = 12.5;
uint32_t val_number32; // 32-bit type
memcpy(&val_number32, &number, sizeof val_number32);
Avoid the cast and assign. It leads to aliasing problems with modern compilers #Andrew.
"... need cast the addresses of a and b to type (unsigned int *) and then dereference the addresses" reflects a risky programing technique.
To test if the bits of the unsigned integer are all zero, simply test with the constant 0.
int bit_all_zero = (val_number32 == 0);
An alternative is to use a union to access the bytes from 2 different encodings.
union {
float val_f;
uint32_t val_u;
} x = { .val_f = 12.5f };
int bit_all_zero = (x.val_u == 0);

Checking if all the bits are zero is equivalent to checking if the number is zero.
So it would be int is_zero = (val_number == 0);

Related

"Bitwise assignment" in C? Assigning a variable's bits to another

Is it possible to do a bitwise assignment in C? (Assigning the bits of a variable to another, assuming for simplicity that the source and the target of assignment have the same number of bits.)
For example, assign the number int 1 (which has bits 0...01) to a float variable, obtaining not the float number 1.0f but the number (assuming IEEE-754 representation and assuming a float is 4 bytes as the int) with bits:
0 (sign) 0000'0000 (exponent) 0...01 (mantissa)
which would be a subnormal number (cause the exponent bits are all 0's and the mantissa is not zero), hence representing the number
+ 2^-126 2^-23 (assuming mantissa has 23 bits, then 0..(23 zeroes in total)..1 is 2^-23), that is 2^-149, that is approx. 1.4 10^-45.
NOTE: I'm in the process of learning. I am not trying to do this in a real-life scenario.
Given two objects a and b that are known to be the same size, you can copy the bits of b into a with memcpy(&a, &b, sizeof a);.
You could use a union for that:
int source;
float target;
union Data {
int i;
float f;
} data;
source = 42;
data.i = source;
target = data.f; // target should now have the bitwise equivalent of 42.
Be mindful about the sizes of the union members. If they are not equal I think they are padded to the right, but to be sure check with the documentation.
You can access the bits of other types via pointers (including memcpy, which takes them as arguments) or via unions. There is already another answer about the former, so I'll focus on the union approach.
Union members share the same memory, so you could use bit fields or integer types to access the individual bits, and then view the same bits by using a member of another type. However, note that both accessing the value of another type via a union and bit fields themselves are implementation defined, so this is inherently non-portable. In particular it is not specified how the bits end up being aligned in relation to other union members…
An example for the case of floats:
#include <stdio.h>
union float_bits {
float value;
struct {
unsigned mantissa:23;
unsigned exponent:8;
unsigned sign:1;
};
struct {
unsigned bits:32;
};
};
static void print_float_bits(union float_bits f) {
printf("(%c %02x %06x) (%08x) %f\n", f.sign ? '-' : '+', (unsigned) f.exponent, (unsigned) f.mantissa, (unsigned) f.bits, f.value);
}
int main(void) {
union float_bits f;
f.value = 1;
print_float_bits(f);
f.sign = 1;
print_float_bits(f);
// Largest normal number
f.sign = 0; f.exponent = 0xFE; f.mantissa = 0x7FFFFF;
print_float_bits(f);
// Infinity
f.exponent = 0xFF; f.mantissa = 0;
print_float_bits(f);
return 0;
}
On my x86-64 machine with 32-bit IEEE-754 floats, compiled with clang, outputs:
(+ 7f 000000) (3f800000) 1.000000
(- 7f 000000) (bf800000) -1.000000
(+ fe 7fffff) (7f7fffff) 340282346638528859811704183484516925440.000000
(+ ff 000000) (7f800000) inf
Disclaimer: Very much implementation defined behaviour, non-portable and dangerous. Bitfields used for readability of the example. Other alternatives would be to put an array of char or some integer type like uint32_t in the union instead of bitfields, but it's still very much implementation defined behaviour.

Hex array to Float

I have an array of
unsigned char array_a[4] = {0x00,0x00,0x08,0x4D};
unsigned char val[4];
float test;
what I want to do is combine all the elements and store it to val to make it 0x0000084D and converter it to float, which is 2125.
I tried memcpy
memcpy(val,array_a,4);
val[4] = '\0';
but still not work.
First, 0x0000084D is the big endian representation of the integer value 2125, not IEEE float.
Second, no need to copy to another char array (and accessing the 5th element out of bounds in an attempt to "nul-terminate" the array). That part makes no sense.
To convert this array to an integer on your host, copy it in a standardized 32 bit integer first, then convert it according to the endianness of your machine (else you'd get a bad value on a little endian machine)
unsigned char array_a[4] = {0x00,0x00,0x08,0x4D};
uint32_t the_int;
memcpy(&the_int,array_a,sizeof(uint32_t));
the_int = ntohl(the_int);
printf("%d\n",the_int);
or without any external conversion libs using bit shifting making it endian-independent:
uint32_t the_int = 0;
int i;
for (i=0;i<sizeof(uint32_t);i++)
{
the_int <<= 8;
the_int += array_a[i];
}
you get 2125 all right, now you can assign it to a float if you like
float test = the_int;

summing unsigned and signed ints, same or different answer?

If I have the following code in C
int main()
{
int x = <a number>
int y = <a number>
unsigned int v = x;
unsigned int w = y;
int ssum = x * y;
unsigned int usum = v * w;
printf("%d\n", ssum);
printf("%d\n", usum);
if(ssum == usum){
printf("Same\n");
} else {
printf("Different\n");
}
return 0;
}
Which would print the most? Would it be equal since signed and unsigned would produce the same result, then if you have a negative like -1, when it gets assigned to int x it becomes 0xFF, and if you want to do -1 + (-1), if you do it the signed way to get -2 = 0xFE, and since the unsigned variables would be set to 0xFF, if you add them you would still get 0xFE. And the same holds true for 2 + (-3) or -2 + 3, in the end the hexadecimal values are identical. So in C is that what's looked at when it sees signedSum == unsignedSum? It doesnt care that one is actually a large number and the other is -2, as long at the 1's and 0's are the same?
Are there any values that would make this not true?
The examples you have given are incorrect in C. Also, converting between signed and unsigned types is not required to preserve bit patterns (the conversion is by value), although with some representations bit patterns are preserved.
There are circumstances where the result of operations will be the same, and circumstances where the result will differ.
If the (actual) sum of adding two ints would overflow an int
(i.e. value outside range that an int can represent) the result is
undefined behaviour. Anything can happen at that point (including
the program terminating abnormally) - subsequently converting to an unsigned doesn't change anything.
Converting an int with negative value to unsigned int uses modulo
arithmetic (modulo the maximum value that an unsigned can
represent, plus one). That is well defined by the standard, but
means -1 (type int) will convert to the maximum value that an
unsigned can represent (i.e. UINT_MAX, an implementation defined
value specified in <limits.h>).
Similarly, adding two variables of type unsigned int always uses
modulo arithmetic.
Because of things like this, your question "which would produce the most?" is meaningless.

C - unsigned int to unsigned char array conversion

I have an unsigned int number (2 byte) and I want to convert it to unsigned char type. From my search, I find that most people recommend to do the following:
unsigned int x;
...
unsigned char ch = (unsigned char)x;
Is the right approach? I ask because unsigned char is 1 byte and we casted from 2 byte data to 1 byte.
To prevent any data loss, I want to create an array of unsigned char[] and save the individual bytes into the array. I am stuck at the following:
unsigned char ch[2];
unsigned int num = 272;
for(i=0; i<2; i++){
// how should the individual bytes from num be saved in ch[0] and ch[1] ??
}
Also, how would we convert the unsigned char[2] back to unsigned int.
Thanks a lot.
You can use memcpy in that case:
memcpy(ch, (char*)&num, 2); /* although sizeof(int) would be better */
Also, how would be convert the unsigned char[2] back to unsigned int.
The same way, just reverse the arguments of memcpy.
How about:
ch[0] = num & 0xFF;
ch[1] = (num >> 8) & 0xFF;
The converse operation is left as an exercise.
How about using a union?
union {
unsigned int num;
unsigned char ch[2];
} theValue;
theValue.num = 272;
printf("The two bytes: %d and %d\n", theValue.ch[0], theValue.ch[1]);
It really depends on your goal: why do you want to convert this to an unsigned char? Depending on the answer to that there are a few different ways to do this:
Truncate: This is what was recomended. If you are just trying to squeeze data into a function which requires an unsigned char, simply cast uchar ch = (uchar)x (but, of course, beware of what happens if your int is too big).
Specific endian: Use this when your destination requires a specific format. Usually networking code likes everything converted to big endian arrays of chars:
int n = sizeof x;
for(int y=0; n-->0; y++)
ch[y] = (x>>(n*8))&0xff;
will does that.
Machine endian. Use this when there is no endianness requirement, and the data will only occur on one machine. The order of the array will change across different architectures. People usually take care of this with unions:
union {int x; char ch[sizeof (int)];} u;
u.x = 0xf00
//use u.ch
with memcpy:
uchar ch[sizeof(int)];
memcpy(&ch, &x, sizeof x);
or with the ever-dangerous simple casting (which is undefined behavior, and crashes on numerous systems):
char *ch = (unsigned char *)&x;
Of course, array of chars large enough to contain a larger value has to be exactly as big as this value itself.
So you can simply pretend that this larger value already is an array of chars:
unsigned int x = 12345678;//well, it should be just 1234.
unsigned char* pChars;
pChars = (unsigned char*) &x;
pChars[0];//one byte is here
pChars[1];//another byte here
(Once you understand what's going on, it can be done without any variables, all just casting)
You just need to extract those bytes using bitwise & operator. OxFF is a hexadecimal mask to extract one byte. Please look at various bit operations here - http://www.catonmat.net/blog/low-level-bit-hacks-you-absolutely-must-know/
An example program is as follows:
#include <stdio.h>
int main()
{
unsigned int i = 0x1122;
unsigned char c[2];
c[0] = i & 0xFF;
c[1] = (i>>8) & 0xFF;
printf("c[0] = %x \n", c[0]);
printf("c[1] = %x \n", c[1]);
printf("i = %x \n", i);
return 0;
}
Output:
$ gcc 1.c
$ ./a.out
c[0] = 22
c[1] = 11
i = 1122
$
Endorsing #abelenky suggestion, using an union would be a more fail proof way of doing this.
union unsigned_number {
unsigned int value; // An int is 4 bytes long
unsigned char index[4]; // A char is 1 byte long
};
The characteristics of this type is that the compiler will allocate memory only for the biggest member of our data structure unsigned_number, which in this case is going to be 4 bytes - since both members (value and index) have the same size. Had you defined it as a struct instead, we would have 8 bytes allocated on memory, since the compiler does its allocation for all the members of a struct.
Additionally, and here is where your problem is solved, the members of an union data structure all share the same memory location, which means they all refer to same data - think of that like a hard link on GNU/Linux systems.
So we would have:
union unsigned_number my_number;
// Assigning decimal value 202050300 to my_number
// which is represented as 0xC0B0AFC in hex format
my_number.value = 0xC0B0AFC; // Representation: Binary - Decimal
// Byte 3: 00001100 - 12
// Byte 2: 00001011 - 11
// Byte 1: 00001010 - 10
// Byte 0: 11111100 - 252
// Printing out my_number one byte at time
for (int i = 0; i < (sizeof(my_number.value)); i++)
{
printf("index[%d]: %u, 0x%x\n", \
i, my_number.index[i], my_number.index[i]);
}
// Printing out my_number as an unsigned integer
printf("my_number.value: %u, 0x%x", my_number.value, my_number.value);
And the output is going to be:
index[0]: 252, 0xfc
index[1]: 10, 0xa
index[2]: 11, 0xb
index[3]: 12, 0xc
my_number.value: 202050300, 0xc0b0afc
And as for your final question, we wouldn't have to convert from unsigned char back to unsigned int since the values are already there. You just have to choose by which way you want to access it
Note 1: I am using an integer of 4 bytes in order to ease the understanding of the concept. For the problem you presented you must use:
union unsigned_number {
unsigned short int value; // A short int is 2 bytes long
unsigned char index[2]; // A char is 1 byte long
};
Note 2: I have assigned byte 0 to 252 in order to point out the unsigned characteristic of our index field. Was it declared as a signed char, we would have index[0]: -4, 0xfc as output.

Bits in C, how do I access the underlying bits in a C float?

Given a two floating point Numbers A and B, which are command line arguments, I must create methods to do bitwise operations on them. Including And, Or, Not, xOr, floating Point addition etc...
How can I access each bit in C? I need to access the specific 1's and 0's. Any idea how?
Here's an example using unions, as Keith suggests.
/* -std=c99 */
#include <stdio.h>
int main(int argc, char * argv[]) {
/* note, I'm assuming an int has the same size of a float here */
assert( sizeof(unsigned int) == sizeof(float) );
union {
float floating;
unsigned int integer;
} a;
a.floating = 3.14;
/* prints the bits in reverse order */
unsigned int temp = a.integer;
for( int i = 0; i < sizeof(float)*8; i++ ) {
printf("%d", temp & 0x1);
temp = temp >> 1;
}
}
EDIT: changed signed ints to unsigned.
by using a union.... you can either get to each part as per :-
What's the correct way of using bitfields in C?
or simply union the whole thing to an unsigned long and then manipulate that.
You have to decide what a bitwise operation on a floating point number should do first, because you can not do bitwise operations on floating point numbers.
If you cast you floating point number to an unsigned type, or separate, the sign, exponent and mantissa into three individual unsigned variables, what should the result of a bit shift be for example?

Resources