I have a function that converts QByteArray
to float
and it works perfectly fine except when I feed it zeros I get 5.87747e-39
instead of 0.0
.
float QByteArrayToFloat(QByteArray f){
bool ok;
int sign = 1;
f = f.toHex(); // Convert to Hex
qDebug() << "QByteArrayToFloat: QByteArray hex = " << f;
f = QByteArray::number(f.toLongLong(&ok, 16), 2); // Convert hex to binary
if(f.length() == 32) {
if(f.at(0) == '1') sign =-1; // If bit 0 is 1 number is negative
f.remove(0,1); // Remove sign bit
}
QByteArray fraction = f.right(23); // Get the fractional part
double mantissa = 0;
for(int i = 0; i < fraction.length(); i++){ // Iterate through the array to claculate the fraction as a decimal.
if(fraction.at(i) == '1')
mantissa += 1.0 / (pow(2, i+1));
}
int exponent = f.left(f.length() - 23).toLongLong(&ok, 2) - 127; // Calculate the exponent
qDebug() << "QByteArrayToFloat: float number = "<< QString::number(sign * pow(2, exponent) * (mantissa + 1.0),'f', 5);
return (sign * pow(2, exponent) * (mantissa + 1.0));
}
There is no useful function in QByteArray
(isEmpty()
doesn't work) that checks for zeros. I could do (after toHex()
) if(f.indexOf("00000000") == -1) return 0.0;
or if(exponent = -127 && mantissa == 0) return 0.0;
, but is there a more elegant solution?
Also, what's interesting is that QString::number(sign * pow(2, exponent) * (mantissa + 1.0),'f', 5);
works just fine and prints "0.00000"
. However, as soon as I transform it back to float with toFloat(&ok);
same thing happens.
I've found out there's a better solution for QByteArray
to float
conversion using bit shifts and reinterpret_cast
. It also handles the zero values.
float QByteArrayToFloat(QByteArray arr)
{
static_assert(std::numeric_limits<float>::is_iec559, "Only supports IEC 559 (IEEE 754) float");
quint32 temp = ((char)arr[0] << 24)|((char)arr[1] << 16)|((char)arr[2] << 8)|(char)arr[3]; // Big endian
float* out = reinterpret_cast<float*>(&temp);
return *out;
}