Ummm. You asked for 15 digits after the decimal point, and that's what it's given you. Seems a bit contrary to complain about that !
The fact that the value is a float, means that 6 decimal digits is about the limit of the precision available (7, if you are confident that you have almost no rounding errors). Asking for 15 decimals, after the '.' is showing you the state of the ls bits of the float, which are affected by rounding and representation errors.
What you appear to want to do is present the value of your float as if it was a double, good to 15 places of decimal, then you need to round the double version of the float to the 6 (or, if you feel brave) 7 decimal digits of precision. This is very similar to what the binary to decimal conversion does anyway, but you need to prepare the double copy of the value, ready for output.
This is not a million miles from getting the string version of the value, to 6 digits, and converting that to double. You can establish for yourself which is quicker !
Unfortunately, there remains an issue. You are asking for 15 decimals after the '.'. This is going to show up the representation errors for values bigger than 10.0, and possibly for values between 1.0 and 10.00. For example: if your float value is (say) 57.51234f (whose actual value is approximately 57.512340545654297); the code below will deliver 575124.0 / 10000.0 as a double, which when output gives: 57.512300000000003 -- because you are asking for approximately 1 digit more than the double has to give. (For 5751.234f the same process gives 5751.229999999999563.)
I would think carefully about why 15 decimals after the '.' is required, especially as the data only has 6-7 digits total precision -- so at most 6-7 "good" digits after the '.', depending on the size of the number.
FWIW: you could convert the number to scientific form, and then massage the string directly -- which is another way of doing what the code below does.
double pt[] = { 1E0, 1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8, 1E9, 1E10, 1E11, 1E12, 1E13, 1E14, 1E15, 1E16, 1E17, 1E18, 1E19 } ; double xx ; int de ; de = 6 - (int)ceilf(log10f(x)) ; /* where 'x' is the float to be shown */ if ((de > 15) || (de < -18)) /* de > 15 -- no need to round, value too small */ /* de < 18 -- cannot round, value too big */ xx = x ; /* xx is value to output */ else { while (1) { xx = x ; if (de < 0) xx /= pt[-de] ; else if (de > 0) xx *= pt[+de] ; xx = round(xx) ; if (xx < pt[5]) de += 1 ; else if (xx > pt[6]) de -= 1 ; else break ; } ; if (de < 0) xx *= pt[-de] ; else if (de > 0) xx /= pt[+de] ; } ; ss << std::fixed << std::setprecision(15) << xx ;
float, you can't expect more than 7 (or so) decimal digits of precision. If you need more digits, you'll have to put up with the cost of usingdouble(or perhaps some user-defined decimal type, to represent your values exactly). I'm afraid there's no way to get more precision out of afloat.