stof、strtof是确定性的吗?

Is stof, strtof deterministic?

我正在从字符串中读取浮点数。它们可以写成各种形式,所以

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

无论前导零和尾随零,我能否确定断言始终为真?分隔符始终是一个点,stof 不处理逗号。

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.

鉴于您的两行代码具有相同数量的有效数字,它们应该表现相同。但这只是基于标准在这里根本没有提到“有效数字”这一事实的推测;它没有在其他任何地方提及,并且该标准没有更明确地说明前导(小数点前)或尾随(小数点后)零。

C++ 14 (§21.5) 标准指出:

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.

因此在许多情况下它们是相同的,但是中间 double 确实打开了 double rounding 的潜力。例如。如果 str = "1.0000000596046448",那么最接近的 float(假设 IEEE754 算法)是 1.0000001f,而最接近的 double 恰好在 1.0f1.0000001f 之间, 因此后续转换为 float 将向下舍入为 1.0f.

至少理论上是这样。然而,在实践中,我无法重新创建:http://ideone.com/NMRy14