TL;DR You stringify objects and encode strings — but this is not an English question.
Greener Pastures
This question probably should not be here, because it does not appear to be English question as all. It appears to be a programming question, and so should be on moved to an SE site that is actually about programming. Programming questions are off-topic here.
Converting data to bytes — or to bits — is a very loose description. What kind of data? You mention 32-bit floats, such as you might do with the printf family of functions. Then again, a 32-bit quantity could be represented as four dotted octets, like
Encode Strings
If you have a logical string that’s being used internally some programming language which you are converting to some external interchange format, then that conversion process is known as encoding your string, such as encoding it in MacRoman or ISO 8859-1, or UTF-8 or UTF-16, et cetera.
When you read in a string from its external representation, you decode it and store it as the logical string object in whatever programming language you’re using. When you write it out again, you encode it from the logical form into some physical form for external interchange.
If you need something tailored to your programming language, those words surely already exist.
Stringify Objects
If what you have is just some random object needing to be externally representable, then you seem to be looking for marshal (which nobody will understand) or stringify (which they will):
stringification
The process of producing a string representation of an abstract object.
―page 1076 of Programming Perl, 4th edition, by Christiansen et al., O’Reilly 2012
Stringify should be preferred over serialize, especially in cases where confusion might arise from its antonymic association with parallelize.
No one will ever know what marshal means, nor be certain of serialize. But of stringify there can be no doubt.
For Programmers Only: Mythbusting 123.4 as a 32-bit float
Whenever you see somebody talking about floating-point numbers (rather than real numbers) like 567.89 or 123.4, they are speaking in an extremely fuzzy and off-the-cuff manner, because those numbers aren’t really there on your computer. This makes whatever conversion process you care to use fuzzy as well.
This is odder than it appears.
Real numbers like 567.89 and 123.4 cannot be exactly represented in 32-bit floating point. That means that whatever your “convert to bytes” notion is, it is going to have to involve either some rounding or else some rather interesting-looking bytes.
Assuming IEEE 754, the closest you can get to the real number 123.4 is something that looks more like 123.400002, or without slop exactly 0x1.ed999ap+6 in hexadecimal floating point notation. Similarly, the closest you can get to the real number 123.3 is floating point 123.300003 or 0x1.ed3334p+6, and the closest you can get to 123.6 is 123.599998 or 0x1.ee6666p+6.
That’s because none of the rational numbers 3/10, 4/10, and 6/10 reduce to a fraction whose denominator is a power of two. So you get slop.
However, 123.5 can be represented exactly, because 5/10
is 1/2, and 2 is obviously a power of 2. So the real number 123.5 is exactly represented by the float 0x1.eep+6. Notice there is no slop there: just 0xEE.
To convert the 32-bit floating point number that’s closest to the real number 123.5 into bytes, you could get away with the four bytes which when read as characters in ISO-8859-1 are “ÍÌöB”. This makes sense: 32 bits is 4 bytes, and 4 bytes are 4 bytes. If you looked at those four bytes as an IP address, they could be 66.246.204.205.
Since we don’t have real numbers here, merely floating point approximations, strange things happen if you aren’t careful. For example, although multiplying floating-point 123.4 by 10 produces 1234 (which is hex 0x1.348p+10 in floating point), adding it together 10 times does not: it instead produces 0x1.348002p+10, which is actually more like 1234.000122 instead of 1234.
Yes, it’s a bit off, but these are closer together than you might think. Via direct multiplication, the octets (on my machine, and probably yours) are 68.154.64.0, but the one you get via tenfold summation are 68.154.64.1. The low bit of the significand is different. So not only is it a bit off, it is exactly one bit off.
To see how this works, merely compile this trivial C program in C99 mode:
#define ITER 10
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <arpa/inet.h>
void cracker(FILE *output, float fnum);
int
main(int argc, char **argv, char **envp) {
FILE *iconv;
if (!(iconv = popen("iconv -f ISO-8859-1 -t UTF-8 | LESSCHARSET=utf-8 less", "w"))) {
perror("popen(iconv,w)");
exit(1);
}
cracker(iconv, 567.89);
float f = 123.4;
fprintf(iconv, "Starting point:\n");
cracker(iconv, f);
float sum = 0;
for (int i = 0; i < ITER; i++) {
sum += f;
}
fprintf(iconv, "Added together %d times:\n", ITER);
cracker(iconv, sum);
fprintf(iconv, "Multiplied by %d:\n", ITER);
cracker(iconv, ITER * f);
cracker(iconv, 123.3);
cracker(iconv, 123.4);
cracker(iconv, 123.5);
cracker(iconv, 123.6);
pclose(iconv);
exit(0);
}
void
cracker(FILE *output, float fnum) {
union {
float fn;
uint32_t un;
unsigned char octets[4];
} polly;
polly.fn = fnum;
struct in_addr in;
in.s_addr = htonl(polly.un);
fprintf(output, "Your hex float is %a\n", polly.fn);
fprintf(output, "Your float is %f\n", polly.fn);
fprintf(output, "Your rounded is %g\n", polly.fn);
fprintf(output, "Your hex int is 0x%X\n", polly.un);
fprintf(output, "Your octets are %s\n", inet_ntoa(in));
fprintf(output, "Your chars are \"%c%c%c%c\"\n\n",
polly.octets[0],
polly.octets[1],
polly.octets[2],
polly.octets[3]
);
}
And then run it to get this output:
Your hex float is 0x1.1bf1ecp+9
Your float is 567.890015
Your rounded is 567.89
Your hex int is 0x440DF8F6
Your octets are 68.13.248.246
Your chars are "öø^MD"
Starting point:
Your hex float is 0x1.ed999ap+6
Your float is 123.400002
Your rounded is 123.4
Your hex int is 0x42F6CCCD
Your octets are 66.246.204.205
Your chars are "ÍÌöB"
Added together 10 times:
Your hex float is 0x1.348002p+10
Your float is 1234.000122
Your rounded is 1234
Your hex int is 0x449A4001
Your octets are 68.154.64.1
Your chars are "^A@<U+009A>D"
Multiplied by 10:
Your hex float is 0x1.348p+10
Your float is 1234.000000
Your rounded is 1234
Your hex int is 0x449A4000
Your octets are 68.154.64.0
Your chars are "^@@<U+009A>D"
Your hex float is 0x1.ed3334p+6
Your float is 123.300003
Your rounded is 123.3
Your hex int is 0x42F6999A
Your octets are 66.246.153.154
Your chars are "<U+009A><U+0099>öB"
Your hex float is 0x1.ed999ap+6
Your float is 123.400002
Your rounded is 123.4
Your hex int is 0x42F6CCCD
Your octets are 66.246.204.205
Your chars are "ÍÌöB"
Your hex float is 0x1.eep+6
Your float is 123.500000
Your rounded is 123.5
Your hex int is 0x42F70000
Your octets are 66.247.0.0
Your chars are "^@^@÷B"
Your hex float is 0x1.ee6666p+6
Your float is 123.599998
Your rounded is 123.6
Your hex int is 0x42F73333
Your octets are 66.247.51.51
Your chars are "33÷B"
As I said, either you will have to do some rounding or else you are going to have to get some rather curious-looking bytes, as the chars
display eventually shows above after it has been run through several backend converters so you can see what they look like without squinting too terribly badly.