QString::number doesn't round
-
Hello,
I have this code:
QString::number(dTotal * 1.19, 'f', 2)
dTotal has a value of 198.135 but it still prints out 198.13 for me and I don't understand why. All other values for example dTotal * 0.19 will be 31.635 which he prints correctly as 31.64
Full code:
painter.drawText(g_preis7, Qt::AlignRight, ""+QString::number(dTotal * 0.19, 'f', 2)+""); painter.drawText(g_preis8, Qt::AlignRight, ""+QString::number(dTotal * 1.19, 'f', 2)+"");
-
Hello,
I have this code:
QString::number(dTotal * 1.19, 'f', 2)
dTotal has a value of 198.135 but it still prints out 198.13 for me and I don't understand why. All other values for example dTotal * 0.19 will be 31.635 which he prints correctly as 31.64
Full code:
painter.drawText(g_preis7, Qt::AlignRight, ""+QString::number(dTotal * 0.19, 'f', 2)+""); painter.drawText(g_preis8, Qt::AlignRight, ""+QString::number(dTotal * 1.19, 'f', 2)+"");
@portstone
198.135 but it still prints out 198.13
31.635 which he prints correctly as 31.64
By what "rounding criteria" are you claiming/assuming the first is incorrect but the second is correct?
Some example discussions of this behaviour are:
- https://stackoverflow.com/questions/24120888/why-printf-round-floating-point-numbers
- https://stackoverflow.com/questions/10357192/printf-rounding-behavior-for-doubles
- https://www.reddit.com/r/perl/comments/80p0rq/printf_rounding_inconsistencies_at_4_decimal/
- https://www.exploringbinary.com/inconsistent-rounding-of-printed-floating-point-numbers/
You need to use a math-type library call if you want more precise control over rounding behaviour.
-
I simply quote Thiago from https://bugreports.qt.io/browse/QTBUG-4280
Not a bug - 'printf("%.2f", 166.5 * 1.19);' also prints 198.13
-
@portstone
198.135 but it still prints out 198.13
31.635 which he prints correctly as 31.64
By what "rounding criteria" are you claiming/assuming the first is incorrect but the second is correct?
Some example discussions of this behaviour are:
- https://stackoverflow.com/questions/24120888/why-printf-round-floating-point-numbers
- https://stackoverflow.com/questions/10357192/printf-rounding-behavior-for-doubles
- https://www.reddit.com/r/perl/comments/80p0rq/printf_rounding_inconsistencies_at_4_decimal/
- https://www.exploringbinary.com/inconsistent-rounding-of-printed-floating-point-numbers/
You need to use a math-type library call if you want more precise control over rounding behaviour.
@jonb because at 5, 6, 7, 8, 9 you round up and that is why it is for me incorrect. But I didn't knew that compilers are handling it with different methods / rules.
-
Hello,
I have this code:
QString::number(dTotal * 1.19, 'f', 2)
dTotal has a value of 198.135 but it still prints out 198.13 for me and I don't understand why. All other values for example dTotal * 0.19 will be 31.635 which he prints correctly as 31.64
Full code:
painter.drawText(g_preis7, Qt::AlignRight, ""+QString::number(dTotal * 0.19, 'f', 2)+""); painter.drawText(g_preis8, Qt::AlignRight, ""+QString::number(dTotal * 1.19, 'f', 2)+"");
The issue here is not related to the links posted above. In those links, the numbers being discussed have exact representations in IEEE-754. However, 198.135 and 31.635 don't fall in this category.
@portstone said in QString::number doesn't round:
dTotal has a value of 198.135 but it still prints out 198.13
It is impossible to store 198.135 in IEEE-754. Your actual value is:
float
: 198.1349945068359375double
: 198.134999999999990905052982270717620849609375
And I expect all compilers to round 198.13499... to 198.13.
All other values for example dTotal * 0.19 will be 31.635 which he prints correctly as 31.64
It is also impossible to store 31.635 in IEEE-754. Your actual value is:
float
: 31.6350002288818359375double
: 31.635000000000001563194018672220408916473388671875
And I expect all compilers to round 31.63500... to 31.64.
I don't understand why.
First, experiment with this tool: https://www.h-schmidt.net/FloatConverter/IEEE754.html
Then, read http://blog.reverberate.org/2014/09/what-every-computer-programmer-should.html
-
The issue here is not related to the links posted above. In those links, the numbers being discussed have exact representations in IEEE-754. However, 198.135 and 31.635 don't fall in this category.
@portstone said in QString::number doesn't round:
dTotal has a value of 198.135 but it still prints out 198.13
It is impossible to store 198.135 in IEEE-754. Your actual value is:
float
: 198.1349945068359375double
: 198.134999999999990905052982270717620849609375
And I expect all compilers to round 198.13499... to 198.13.
All other values for example dTotal * 0.19 will be 31.635 which he prints correctly as 31.64
It is also impossible to store 31.635 in IEEE-754. Your actual value is:
float
: 31.6350002288818359375double
: 31.635000000000001563194018672220408916473388671875
And I expect all compilers to round 31.63500... to 31.64.
I don't understand why.
First, experiment with this tool: https://www.h-schmidt.net/FloatConverter/IEEE754.html
Then, read http://blog.reverberate.org/2014/09/what-every-computer-programmer-should.html
@jksh
At first in my reply I wrote about maybe the numbers OP was using did not have the representation he expected when as a float/double. Then I thought I had no evidence for that so I scrubbed that part. Looks like I should have stuck with it!I did not know there was a tool like you mention which allows to easily examine what the representation is. How did you know other numbers do have "exact" representation while the numbers the OP mentions do not? I have typed some random (floating) numbers into the tool and as far as I can see none of them have an exact. For x.yz5 they all vary between like x.yz499... and x.yz501.... So I would sort of expect the 0.005 at the end of such numbers to round as 0.00499 half of the time and 0.00501 the other half, i.e. half the time round down, half the time round up. Is that right?
Second question: let's say I want to round my numbers to even, e.g. 1.235 -> 1.24, 1.285 -> 1.28. There are libraries to do that. But that seems to me to rely on the number with the trailing 0.005 starting out with exactly that representation, because the rounding to even only applies to numbers ending in 5. How does that work if much of the time you cannot even get an accurate representation which really does end in a 5, if it's always ....4999... or ...5001... then the even rounding won't be invoked?
-
@jksh
At first in my reply I wrote about maybe the numbers OP was using did not have the representation he expected when as a float/double. Then I thought I had no evidence for that so I scrubbed that part. Looks like I should have stuck with it!I did not know there was a tool like you mention which allows to easily examine what the representation is. How did you know other numbers do have "exact" representation while the numbers the OP mentions do not? I have typed some random (floating) numbers into the tool and as far as I can see none of them have an exact. For x.yz5 they all vary between like x.yz499... and x.yz501.... So I would sort of expect the 0.005 at the end of such numbers to round as 0.00499 half of the time and 0.00501 the other half, i.e. half the time round down, half the time round up. Is that right?
Second question: let's say I want to round my numbers to even, e.g. 1.235 -> 1.24, 1.285 -> 1.28. There are libraries to do that. But that seems to me to rely on the number with the trailing 0.005 starting out with exactly that representation, because the rounding to even only applies to numbers ending in 5. How does that work if much of the time you cannot even get an accurate representation which really does end in a 5, if it's always ....4999... or ...5001... then the even rounding won't be invoked?
@jonb said in QString::number doesn't round:
How did you know other numbers do have "exact" representation while the numbers the OP mentions do not?
I opened the links that you and @Christian-Ehrlicher posted, found the test numbers, and plugged those numbers into https://www.h-schmidt.net/FloatConverter/IEEE754.html. Then, I did the same with the OP's numbers :)
I have typed some random (floating) numbers into the tool and as far as I can see none of them have an exact. For x.yz5 they all vary between like x.yz499... and x.yz501....
There are infinitely more real numbers that have no exact representation in IEE-754, compared to real numbers that do have exact representations. So statistically, a randomly-chosen number has a negligible chance of being exactly representable as a
float
/double
.To easily find a number with an exact representation, divide 2 by an integer. 2, 1, 0.5, 0.25, 0.125, 0.0625, 0.03125, ... have exact representations.
So I would sort of expect the 0.005 at the end of such numbers to round as 0.00499 half of the time and 0.00501 the other half, i.e. half the time round down, half the time round up. Is that right?
My gut feeling agrees with you, but I don't have any proof at the moment.
Second question: let's say I want to round my numbers to even, e.g. 1.235 -> 1.24, 1.285 -> 1.28. There are libraries to do that. But that seems to me to rely on the number with the trailing 0.005 starting out with exactly that representation, because the rounding to even only applies to numbers ending in 5. How does that work if much of the time you cannot even get an accurate representation which really does end in a 5, if it's always ....4999... or ...5001... then the even rounding won't be invoked?
I've never tried it myself, but there are publicly available implementations: https://stackoverflow.com/questions/32246103/rounding-doubles-to-n-decimal-points-using-round-to-even-in-c
-
@jonb said in QString::number doesn't round:
How did you know other numbers do have "exact" representation while the numbers the OP mentions do not?
I opened the links that you and @Christian-Ehrlicher posted, found the test numbers, and plugged those numbers into https://www.h-schmidt.net/FloatConverter/IEEE754.html. Then, I did the same with the OP's numbers :)
I have typed some random (floating) numbers into the tool and as far as I can see none of them have an exact. For x.yz5 they all vary between like x.yz499... and x.yz501....
There are infinitely more real numbers that have no exact representation in IEE-754, compared to real numbers that do have exact representations. So statistically, a randomly-chosen number has a negligible chance of being exactly representable as a
float
/double
.To easily find a number with an exact representation, divide 2 by an integer. 2, 1, 0.5, 0.25, 0.125, 0.0625, 0.03125, ... have exact representations.
So I would sort of expect the 0.005 at the end of such numbers to round as 0.00499 half of the time and 0.00501 the other half, i.e. half the time round down, half the time round up. Is that right?
My gut feeling agrees with you, but I don't have any proof at the moment.
Second question: let's say I want to round my numbers to even, e.g. 1.235 -> 1.24, 1.285 -> 1.28. There are libraries to do that. But that seems to me to rely on the number with the trailing 0.005 starting out with exactly that representation, because the rounding to even only applies to numbers ending in 5. How does that work if much of the time you cannot even get an accurate representation which really does end in a 5, if it's always ....4999... or ...5001... then the even rounding won't be invoked?
I've never tried it myself, but there are publicly available implementations: https://stackoverflow.com/questions/32246103/rounding-doubles-to-n-decimal-points-using-round-to-even-in-c
@jksh said in QString::number doesn't round:
There are infinitely more real numbers that have no exact representation in IEE-754, compared to real numbers that do have exact representations. So statistically, a randomly-chosen number has a negligible chance of being exactly representable as a float/double.
Yes, that is indeed a good point! And someone who actually knows to use the word "infinite" correctly :)
To easily find a number with an exact representation, divide 2 by an integer. 2, 1, 0.5, 0.25, 0.125, 0.0625, 0.03125, ... have exact representations.
I regard that as cheating! Clearly I did not intend to ask about floats reached by dividing integers by 2, which even my cat understands are representable in IEEE ;-)