Widening precision with cast results in how much precision?
-
21-12-2019 - |
Question
I know that widening conversions are safe in that they result in no loss of data, but is there a real gain in precision or is it a longer representation with the same number of signifigant figures?
For example,
#include <iostream>
#include <iomanip>
int main()
{
float i = 0.012530f;
std::cout << std::setw(20) << std::setprecision(7) << i << std::endl;
double ii = (double)i;
std::cout << std::setw(20) << std::setprecision(15) << ii << std::endl;
double j = 0.012530;
std::cout << std::setw(20) << std::setprecision(15) << j << std::endl;
}
Produces the output
0.01253
0.012529999949039
0.01253
Looking at the variables in the debugger shows that j
is rounded as floating point cannot represent the original number exactly, but it is still a more exact approximation of the original number than ii
.
i = 0.012530000
ii = 0.012529999949038029
j = 0.012529999999999999
Why is it that the cast is less exact than the direct assignment? Can I only count on 8 digits of exactitude if I widen the precision of a float?
Solution
It seems like the answer to your question is obvious. Because double
holds more precision than float
, you get a more precise value if you assign directly to a double
and lose precision if you go through a float
.
When you do float i = 0.012530f;
you get a float
that's as close to 0.01253 as a float
can get. To 7 digits, that looks like 0.012530
.
When you do double j = 0.012530;
, you get a double
that's as close to 0.01253 as a double
can get.
If you cast the float
to a double
, you get a double
that's as close to 0.01253 as a float
can get.
You can't really compare numbers output to different precisions to see which is closer. For example, say the correct number is 0.5, and you have two approximations, "0.5001" and "0.49". Clearly, the first is better. But if you display the first with 5 decimal digits "0.5001" and the second with only one decimal digit "0.5", the second looks closer. Your first output has this kind of false, apparent precision due to showing with few digits and lucky rounding.