Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert a char array to a float array?

In order to train a classifier, it requires that the training data are specified using a set of float array. Unfortunately, the training data available to me are byte arrays (actually they are Ipp8u arrays, which can be converted to unsigned char arrays).

Essentially, given an unsigned char array, I need to convert it to a float array: in other words, given an unsigned char array, I should read it as a float array. Is this operation always allowed? Does the float data type allow all possible configurations of bits? If yes, how to implement this conversion?

like image 992
enzom83 Avatar asked Dec 03 '25 17:12

enzom83


3 Answers

There are many ways to approximate real numbers. There are floating point representations where some bits represent an exponent and some other bits represent a coefficient, there are fixed point representations where some bits represent the whole number part and some bits represent the factional part, there are arbitrary finite precision representations where some number of 'digits' in some base are stored, etc., and for every general class of representation there is an infinite variety of details which would matter when converting that representation into floats.

Your question does not specify what representation the byte array contains. Specifying that the array is Ipp8u does not come close to providing the necessary information.


What you probably mean is that the byte array contains a byte representation of the machine's native representation of floats (which is probably IEEE-754), differing at most in endianess.

You can simply do a memcpy of data from the char array into an array of floats:

char c[10 * sizeof(float)] = {...};
float f[10];
std::memcpy(f, c, 10 * sizeof(float)); // or you can search for an implementation of bit_cast

One thing not to do is to simply cast the char array: float *f = reinterpret_cast<float*>(c); This cast probably has undefined behavior because float probably has stricter alignment requirements than char.

If the endianess differs then you go through the byte array first and reorder the bytes, something like this:

// assuming sizeof(float) == sizeof(uint32_t)
for (int i; i<sizeof c; i+=sizeof(float)) {
    uint32_t i;
    std::memcpy(&i, c + i, sizeof(uint32_t));
    ntoh(i); // swaps bytes from Network TO Host order.
    std::memcpy(c + i, &i, sizeof(uint32_t));
}
like image 80
bames53 Avatar answered Dec 06 '25 08:12

bames53


There are many ways to approximate real numbers. There are floating point representations where some bits represent an exponent and some other bits represent a coefficient, there are fixed point representations where some bits represent the whole number part and some bits represent the factional part, there are arbitrary finite precision representations where some number of 'digits' in some base are stored, etc., and for every general class of representation there is an infinite variety of details which would matter when converting that representation into floats.

Your question does not specify what representation the byte array contains. Specifying that the array is Ipp8u does not come close to providing the necessary information.


What you probably mean is that the byte array contains a byte representation of the machine's native representation of floats (which is probably IEEE-754), differing at most in endianess.

You can simply do a memcpy of data from the char array into an array of floats:

char c[10 * sizeof(float)] = {...};
float f[10];
std::memcpy(f, c, 10 * sizeof(float)); // or you can search for an implementation of bit_cast

One thing not to do is to simply cast the char array: float *f = reinterpret_cast<float*>(c); This cast probably has undefined behavior because float probably has stricter alignment requirements than char.

If the endianess differs then you go through the byte array first and reorder the bytes, something like this:

// assuming sizeof(float) == sizeof(uint32_t)
for (int i; i<sizeof c; i+=sizeof(float)) {
    uint32_t i;
    std::memcpy(&i, c + i, sizeof(uint32_t));
    ntoh(i); // swaps bytes from Network TO Host order.
    std::memcpy(c + i, &i, sizeof(uint32_t));
}
like image 28
bames53 Avatar answered Dec 06 '25 08:12

bames53


Given the documentation of the Intel Integrated Performance Primitives, the function:

IppStatus ippsConvert_8u32f(const Ipp8u* pSrc, Ipp32f* pDst, int len);

would seem a most-handy function for doing exactly what you're looking for.

like image 33
WhozCraig Avatar answered Dec 06 '25 06:12

WhozCraig