[英]QbyteArray to float
我有一个将QByteArray
转换为float
的函数,它工作得很好,除非当我将其喂入零时,得到5.87747e-39
而不是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));
}
QByteArray
没有有用的函数( isEmpty()
不起作用)检查零。 我可以做(在toHex()
) if(f.indexOf("00000000") == -1) return 0.0;
或if(exponent = -127 && mantissa == 0) return 0.0;
,但是还有更优雅的解决方案吗?
另外,有趣的是QString::number(sign * pow(2, exponent) * (mantissa + 1.0),'f', 5);
可以正常工作并显示"0.00000"
。 但是,一旦我将其转换回使用toFloat(&ok);
同样的事情发生。
我从这份文件中引用:
非正规数
如果您有一个全为零的指数字段,这就是所谓的非规范化数字。 在指数字段等于零的情况下,您会认为实际指数将为-127,因此该数字将采用1.MANTISSA * 2-127的形式,如上所述,但事实并非如此。 而是0.MANTISSA * 2-126。 请注意,指数不再是指数字段的值减去127。它只是-126。 还要注意,我们不再为尾数添加隐含的一位。
零
您可以将零视为另一个非正规数。 零表示为零的指数,尾数为零。 根据我们对非规范化数字的理解,这转化为0 * 2-126 =0。此符号位可以为正(0)或负(1),从而导致正或负零。 从数学上讲这没有多大意义,但是允许这样做。
在将您的代码更正为零的情况下:
int exponent = - 126;
// and
return (sign * pow(2, exponent) * (mantissa + 0.0));
我得到答案0.0 。
我发现QByteArray
有一个更好的解决方案,可以使用移位和reinterpret_cast
进行float
转换。 它还处理零值。
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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.