Bug in conversion from double to integer (only some value)
-
wrote on 31 May 2024, 06:59 last edited by JAHT
Hello:
A very strange thing happens to me with the following lineuint8_t aux1;
aux1=(uint8_t)(ui->His16Edit->text().toDouble(&ok)*10);
were aux1 is uint8_t and His16Edit is a QLineEdit
with de 1.6 vaule at the QLineEdit, aux1 is 16
with de 1.8 vaule at the QLineEdit, aux1 is 18
but with de 1.7 vaule at the QLineEdit, the result at aux1 is 16, ??????If I use a double intermediate variable aux2
aux2=ui->His16Edit->text().toDouble(&ok); aux1=(aux2*10.0f);
the same thing happens, aux2 take the 1.7 value, but at the end aux 1 is wrong and take 16.
the only way to have right value is
aux2=ui->His16Edit->text().toDouble(&ok)*10; aux1=aux2;
Here aux2 is 17.0 and aux1 is 17.
What worries me is that it only happens with the value of 1.7 and that I have seen by chance, and I do not find a way to do it in a compact script with typecast and the extent of this failure in other double to integer conversions
QT Creator 4.15.2
Based on Qt 5.15.2 (MSVC 2019, 64 bit)
Built on Jul 13 2021 01:18:34
From revision 94d227cd43 -
This is working fine for me:
QString s16 = "1.6"; QString s17 = "1.7"; QString s18 = "1.8"; auto i16 = uint8_t(s16.toDouble() * 10); auto i17 = uint8_t(s17.toDouble() * 10); auto i18 = uint8_t(s18.toDouble() * 10); qDebug() << int(i16) << int(i17) << int(i18);
Please provide a minimal, compilable example of your problem - no QLineEdit needed as I showed you.
Also we don't care what QtCreator version you are using but the used Qt version. -
wrote on 31 May 2024, 07:54 last edited by
I have made a program as you said and the result is 16,16,18.
Sorry the version is Qt 5.15.2 MinGW_32_bit
I think is a bug from this version Qt 5.15.2 MinGW_32_bitA colleague have tested with Qt 6.6.0 MinGW_32_bit has the right value.
16,17,18. -
I have made a program as you said and the result is 16,16,18.
Sorry the version is Qt 5.15.2 MinGW_32_bit
I think is a bug from this version Qt 5.15.2 MinGW_32_bitA colleague have tested with Qt 6.6.0 MinGW_32_bit has the right value.
16,17,18.wrote on 31 May 2024, 08:15 last edited by@JAHT said in Bug in conversion from double to integer (only some value):
I think is a bug from this version Qt 5.15.2 MinGW_32_bit
Rather worrying!....
-
I dobut there is a bug in such a simple thing.
Please provide the output of the three toDouble() without multiplication. -
wrote on 31 May 2024, 08:28 last edited by
The double value are right.
QString s16 = "1.6"; QString s17 = "1.7"; QString s18 = "1.8"; auto i16 = uint8_t(s16.toDouble() * 10); auto i17 = uint8_t(s17.toDouble() * 10); auto i18 = uint8_t(s18.toDouble() * 10); qDebug() << s16.toDouble() << s17.toDouble() << s18.toDouble(); qDebug() << int(i16) << int(i17) << int(i18);
10:27:17: Starting D:\TrabajoJose\DoubleConversion\build-DoubleConversion-Desktop_Qt_5_15_2_MinGW_32_bit-Debug\debug\DoubleConversion.exe ...
1.6 1.7 1.8
16 16 18 -
So no Qt problem here.
-
So no Qt problem here.
wrote on 31 May 2024, 08:39 last edited by JonB@Christian-Ehrlicher , @JAHT
uin8_t(double)
does floor not any kind of round, right? So a tiny difference where what shows as1.7
is actually1.6999999999999
and* 10
gives16.999999999
would be enough foruint_t()
to produce16
rather than17
? Still not sure why 32-bit worse than 64-bit, are doubles not 64-bit in both (try printingsizeof(double)
in each)? I think this code should not directly useuint_t(double)
, some sort of mathround()
first? Or add0.5
likeuint8_t(s17.toDouble() * 10 + 0.5);
? I always add 0.5 (or 0.4999 depending on what you want to happen tox.5
) beforeint
ing adouble
. -
wrote on 31 May 2024, 08:52 last edited by
Yes, it seems that that is the issue, I was wrong when saying the version used by my colleague that it worked, it is Qt 6.6.0 MinGW_64_bit
-
Lifetime Qt Championwrote on 31 May 2024, 08:53 last edited by Christian Ehrlicher
Again: this has nothing to do with Qt but maybe with the compiler you're using (mingw version whatever). And @JonB is correct - you should round your number before otherwise it's truncated.
-
Yes, it seems that that is the issue, I was wrong when saying the version used by my colleague that it worked, it is Qt 6.6.0 MinGW_64_bit
wrote on 31 May 2024, 08:53 last edited by JonB@JAHT
I am a bit lost as to whether you now say it does or does not work correctly in 64-bit MinGW. But in any case if you think about it I suggest you always add 0.5/0.4999 to adouble
before youint
it if you want it rounded not floored. -
wrote on 31 May 2024, 09:08 last edited by
Thank you for your suggestion.
With 32-bit MinGW it doesn´t work and with 64-bit MinGW it works
-
wrote on 31 May 2024, 09:15 last edited by JonB
If 32-bit MinGW says
unit_t(1.7 * 10 + 0.5) == 16
I would be surprised/shocked, and worry about anything (at least with floating point) compiled with it, but I cannot test.... -
wrote on 31 May 2024, 09:24 last edited by JAHT
Yes with:
QString s16 = "1.6"; QString s17 = "1.7"; QString s18 = "1.8"; auto i16 = uint8_t(s16.toDouble() * 10+0.5); auto i17 = uint8_t(s17.toDouble() * 10+0.5); auto i18 = uint8_t(s18.toDouble() * 10+0.5); qDebug() << s16.toDouble() << s17.toDouble() << s18.toDouble(); qDebug() << int(i16) << int(i17) << int(i18);
The result is as expected with MingW_32
11:22:25: Starting D:\TrabajoJose\DoubleConversion\build-DoubleConversion-Desktop_Qt_5_15_2_MinGW_32_bit-Debug\debug\DoubleConversion.exe ...
1.6 1.7 1.8
16 17 18Thank you very much @Christian-Ehrlicher @JonB
-
Yes with:
QString s16 = "1.6"; QString s17 = "1.7"; QString s18 = "1.8"; auto i16 = uint8_t(s16.toDouble() * 10+0.5); auto i17 = uint8_t(s17.toDouble() * 10+0.5); auto i18 = uint8_t(s18.toDouble() * 10+0.5); qDebug() << s16.toDouble() << s17.toDouble() << s18.toDouble(); qDebug() << int(i16) << int(i17) << int(i18);
The result is as expected with MingW_32
11:22:25: Starting D:\TrabajoJose\DoubleConversion\build-DoubleConversion-Desktop_Qt_5_15_2_MinGW_32_bit-Debug\debug\DoubleConversion.exe ...
1.6 1.7 1.8
16 17 18Thank you very much @Christian-Ehrlicher @JonB
@JAHT said in Bug in conversion from double to integer (only some value):
+0.5
use a proper round function or you will get wrong results with negative numbers.
-
wrote on 31 May 2024, 09:41 last edited by
Great that is working now. But can you please write
s16.toDouble() * 10 + 0.5
rather than* 10+0.5
as that just encourages mis-reading :)@Christian-Ehrlicher said in Bug in conversion from double to integer (only some value):
use a proper round function or you will get wrong results with negative numbers.
Never thought about that as I don't have negative numbers! What would you suggest? Because I am worried that
round()
from the math library delivers its result as adouble
not anint
. Then if the conversion of that fromdouble
toint
still has some tiny floating point precision issue, as your tests claim to show, I am wondering if that still might produce 16 where it ought be 17...? -
Great that is working now. But can you please write
s16.toDouble() * 10 + 0.5
rather than* 10+0.5
as that just encourages mis-reading :)@Christian-Ehrlicher said in Bug in conversion from double to integer (only some value):
use a proper round function or you will get wrong results with negative numbers.
Never thought about that as I don't have negative numbers! What would you suggest? Because I am worried that
round()
from the math library delivers its result as adouble
not anint
. Then if the conversion of that fromdouble
toint
still has some tiny floating point precision issue, as your tests claim to show, I am wondering if that still might produce 16 where it ought be 17...?wrote on 3 Jun 2024, 06:46 last edited by@JonB said in Bug in conversion from double to integer (only some value):
Because I am worried that round() from the math library delivers its result as a double not an int.
Well, there are also
lround
andllround
(https://en.cppreference.com/w/cpp/numeric/math/round). Hopefully, these two functions don't provide any problems with corner cases. -
@JonB said in Bug in conversion from double to integer (only some value):
Because I am worried that round() from the math library delivers its result as a double not an int.
Well, there are also
lround
andllround
(https://en.cppreference.com/w/cpp/numeric/math/round). Hopefully, these two functions don't provide any problems with corner cases.wrote on 3 Jun 2024, 07:02 last edited by@SimonSchroeder I didn't know about
std::lround()
, that should be acceptable if preferred to adding 0.5 and then takingint
.
1/18