3

I'm reading floats from a string. They can be written in a various form, so

float f1 = strtof("999999999999.16");
float f2 = stof("000999999999999.1600000");
assert(f1 == f2);

Can I be sure that the assertion will be always true, no matter of leading and trailing zeros? The separator will be always a dot, stof doesn't handle the comma.

marmistrz
  • 5,974
  • 10
  • 42
  • 94
  • Not 100% sure. `stof` calls `strtod` internally so I do not know if that will make a difference or not. In C++17 it will call `strtof` internally so it should be guaranteed then. – NathanOliver Oct 06 '16 at 16:23
  • I'm not 100% sure either. I think this question needs a standards reference. @SnoopDog answer as it stands ought to be regarded as little more than conjecture. – Bathsheba Oct 06 '16 at 16:28

2 Answers2

3

The C11 standard, in 7.22.1.3p9, has this to say about C's strtof/strtod/strtold (which should be what the C++ versions use underneath, at least judging from cppreference):

If the subject sequence has the decimal form and at most DECIMAL_DIG (defined in <float.h>) significant digits, the result should be correctly rounded.

Given that both of your code lines have the same number of significant digits, they should behave the same. But this is merely conjecture based on the fact that the standard mentions “significant digits” here at all; it is not mentioned anywhere else, and the standard does not say anything more explicit regarding leading (before the decimal point) or trailing (after the decimal point) zeroes.

mindriot
  • 5,413
  • 1
  • 25
  • 34
1

The C++ 14 (§21.5) standard states that:

float stof(const string& str, size_t* idx = 0);

double stod(const string& str, size_t* idx = 0);

long double stold(const string& str, size_t* idx = 0);

Effects: the first two functions call strtod(str.c_str(), ptr) and the third function calls strtold( str.c_str(), ptr). Each function returns the converted result, if any. The argument ptr designates a pointer to an object internal to the function that is used to determine what to store at *idx. If the function does not throw an exception and idx != 0, the function stores in *idx the index of the first unconverted element of str.

In many cases therefore they will be the same, but the intermediate double does open the potential for double rounding. E.g. if str = "1.0000000596046448", then the closest float (assuming IEEE754 arithmetic) is 1.0000001f, whereas the closest double is exactly halfway between 1.0f and 1.0000001f, and so subsequent conversion to float will round down to 1.0f.

That's the theory at least. In practice, however, I am unable to recreate this: http://ideone.com/NMRy14

Simon Byrne
  • 7,694
  • 1
  • 26
  • 50