Suppose you have a string like "0.1" that can be only approximately represented as a binary floating point number, and you want to convert it to single precision floating point. This can be done as
strtof(s, 0);
or
(float)strtod(s, 0);
Intuitively, these should give the same result, but is intuition correct in all cases? Or are there any edge cases in which the second form, by doing the rounding twice, gives a slightly different result from the first form?
The C standard's specification of
strtodandstrtofis underspecified. It leaves room for the possibility thatstrtofreturns(float)strtodalways, very often or never. (This paragraph refers to another section of the standard that contains that paragraph, which says “the result is either the nearest representable value, or the larger or smaller representable value immediately adjacent to the nearest representable value, chosen in an implementation-defined manner”).The typical implementations of
strtodandstrtofreturn respectively the nearestdoubleand the nearestfloatto the decimal representation passed to them. When these functions behave this way, thenstrtof(s, 0)is almost always identical to(float)strtod(s, 0). The decimal representations for which they are not identical are said to exhibit a double-rounding problem, because rounding the decimal representation first todoubleand then tofloatproduces a different result than rounding directly tofloat. Note that when this happens, thestrtofresult is the more exact one. The intermediate rounding made the error slightly more than half a ULP rather than slightly less than half a ULP.One example of decimal representation with a double-rounding problem when going through
doublebefore converting tofloatis1.01161128282547(taken from this quiz). The nearestdoubleis exactly halfway between twofloats. Rounding directly tofloatgets you the nearestfloat, and going through the nearestdoubleproduces the otherfloat.