繁体   English   中英

QbyteArray浮动

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM