# Convert quint16 to float number

• Hi everybody,
my question is not really Qt specific, but my search through the internet wasn't successful.

I get a quint16 number (representing a floating number) from a function and want to convert it to a floating number https://en.wikipedia.org/wiki/Half-precision_floating-point_format

Like:

``````float quint16ToFloat(quint16 value)
{
// insert magic stuff

return myFloat;
}
``````

Can anybody help?

Thanks

[Moved to C++ Gurus ~kshegunov]

• Hi,
Try something along these lines:

``````float quint16ToFloat(quint16 value)
{
union  {
quint16 v;
struct  {
qint8 sign : 1;
qint8 exponent: 5;
qint16 fraction: 10;
} frep;
} halfPrecisionFloat;

union  {
float v;
struct  {
qint8 sign : 1;
qint8 exponent: 8;
qint16 fraction: 23;
} frep;
} singlePrecisionFloat;

halfPrecisionFloat.v = value;
singlePrecisionFloat.frep.sign = halfPrecisionFloat.frep.sign;
singlePrecisionFloat.frep.exponent = halfPrecisionFloat.frep.exponent;
singlePrecisionFloat.frep.fraction = halfPrecisionFloat.frep.fraction;

return singlePrecisionFloat.v;
}
``````

... or alternatively ...

``````float quint16ToFloat(quint16 value)
{
quint32 result = (static_cast<quint32>(value & 0x8000) << 16) | (static_cast<quint32>(value & 0x7FF) << 13);
return *reinterpret_cast<float *>(&result); // ... don't ask ...
}
``````

Warning:
You should bear in mind, however, that the first snippet is relying on the C++ compiler following the C99 standard, not the C++11 on unions (which is the case in my experience, but still ...!). In the latter reading an uninitialized field from a union is undefined, the former has defined behavior. The second code snippet isn't all roses either, it allows for alignment specific problems (because of the nasty reinterpret at the end).

EDIT:
I've corrected an error in the second snippet. The mantissa bits should be aligned to the rightmost possible significant bit as they're inverse powers (i.e. 1/2, 1/4, 1/8 etc).

Kind regards.

• Depending on your platform there might be more options, e.g. compiler extensions.

• @Wieland
The application will be run on windows, x86 architecture.

I found some good papers like http://blog.schmorp.de/data/binary16/fasthalffloatconversion.pdf

I didn't expect that the conversion is such difficult.

The data i will receive are temperatures of a modus tcp register from this module

In my case the temperature range is between +20°C to +500°C.

• I found some good papers like http://blog.schmorp.de/data/binary16/fasthalffloatconversion.pdf

Good find. I've forgotten about the special values ... *_* sounds silly for a person bragging about knowing floating point arithmetic inside out ... :)

I didn't expect that the conversion is such difficult.

It's not a native type, that's the reason, you don't have hardware support for half-precision fp numbers.

• @kshegunov

So i have just implemented the formula given here

``````float quint16ToFloat(const quint16 & value)
{
int sign = value >> 15 & 1;

int exponent = 0;
for (int i = 10; i <=14; i++)
exponent |= (value >> i & 1) << (i - 10);

float mantissa = 0;
for (int i = 0; i <= 9; i++)
mantissa +=  (value >> i & 1) * qPow(2.0, -1.0 * (9 - i + 1));

if (exponent >= 1 && exponent <= 30)
mantissa +=1;

if (exponent == 0 && mantissa == 0)
return 0.0;

if (exponent == 31 && mantissa == 0)
; //infinity

if (exponent == 31 && mantissa != 0)
; // Nan

qDebug() << "Sign: " << sign;
qDebug() << "Exponent: " << exponent - 15;
qDebug() << "Mantissa: " << mantissa;

return qPow(-1.0, sign) * qPow(2.0, exponent - 15) * mantissa;
}

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

quint16 value = 20384; // Operand A = 30.5 = 0 10011 1110100000 = 20384

qDebug() << "quint16: " << value << "float: " << quint16ToFloat(value);

return a.exec();
}
``````

Output:
Sign: 0
Exponent: 4
Mantissa: 1.90625
quint16: 20384 float: 30.5

Here is a online converter and i get the same results http://oletus.github.io/float16-simulator.js/

It seems to work.

• @beecksche I'm wondering why they use floating point numbers for that (which are not even standardised!)? Why not use uint16 and represent 1°C as lets say 10?
Then 20,5 would be 205.
I hope they do not develop anything for financial area using floating point numbers :-)

• @jsulm
You're right! I misinterpreted the documentation of the temperature module.
Today i've tested it and get the wrong temperatures.

In the module you can set a temperature resolution: 0.01 °C or 0.1 °C. The value i get is a 16 bit value, the 15th bit is the sign and the other 15 bit (0 - 14) represent the temperature depending in the set resolution.

Resolution Data Bits Sign Value Temperature
0.01 2046 0 000011111111110 + 2046 20.46
0.1 204 0 000000011001100 + 204 20.4
0.1 32972 1 000000011001100 - 204 -20.4

So it isn't that difiicult as i thought at the beginning. But now i know to convert a 16 bit float value ;-)

Thanks for help!

• I hope they do not develop anything for financial area using floating point numbers :-)

As far as my understanding goes, fixed point arithmetic is still the technique of choice for financial (or rather accounting) applications.

But now i know to convert a 16 bit float value ;-)

Not that you will ever need it ... ;)
... but I'm glad you found a solution.

Kind regards.

• Since Qt 5.9.0 there's a qfloat16 class to handle half-float values https://wiki.qt.io/New_Features_in_Qt_5.9 and https://doc.qt.io/qt-5/qfloat16.html.

The class is based on the algorithms described in the paper http://blog.schmorp.de/data/binary16/fasthalffloatconversion.pdf