stof和strtof是确定性的吗?

3

我正在从一个字符串中读取浮点数。浮点数可以用各种形式表示,因此

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

我能确保这个断言始终是正确的吗?无论前导零和末尾零如何,分隔符永远是一个点(“.”),因为stof不能处理逗号(“,”)。


不是100%确定。stof在内部调用strtod,所以我不知道这是否会有所不同。在C++17中,它将在内部调用strtof,因此那时应该是有保证的。 - NathanOliver
我也不是100%确定。我认为这个问题需要一个标准的参考。@SnoopDog的回答应该被视为不太可靠的猜测。 - Bathsheba
2个回答

3

C11标准中的7.22.1.3p9对于C语言的strtof/strtod/strtold(至少从cppreference上看,这些函数应该是C++版本所使用的)有如下规定:

如果主体序列具有小数形式,并且最多有DECIMAL_DIG(在<float.h>中定义)个有效数字,则结果应正确舍入。

考虑到你的两行代码都具有相同数量的有效数字,它们应该表现相同。但这仅仅是基于标准在此处提到“有效数字”的推测;在其他任何地方都没有提到,标准也没有关于前导零(小数点之前)或尾随零(小数点之后)的更明确说明。


你确定两者都使用 strtof 吗? Cplusplus 提到 stof 使用的是 strtod,但并未提及与 stof 相似的内容。 - 463035818_is_not_a_number
@tobi303 cppreference提到strtof作为“底层函数”(在脚注中;虽然没有更好的参考)。 - mindriot
@mindriot stof 在 C++17 之前调用 strtod,在 C++17 中将调用 strtof - NathanOliver

1

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);

作用:前两个函数调用 strtod(str.c_str(), ptr),第三个函数调用 strtold( str.c_str(), ptr)。每个函数返回转换后的结果(如果有)。参数 ptr 指定一个指针,指向函数内部用于确定存储在 *idx 处的内容的对象。如果函数没有引发异常并且 idx != 0,则函数会将 str 的第一个未转换的元素的索引存储在 *idx 中。

在很多情况下,它们将是相同的,但中间的“double”确实打开了双重舍入的潜力。例如,如果str = "1.0000000596046448",那么最接近的float(假设IEEE754算术)是1.0000001f,而最接近的double正好在1.0f1.0000001f之间,因此随后转换为float将向下舍入为1.0f
至少在理论上是这样。然而,在实践中,我无法重现这个问题:http://ideone.com/NMRy14

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接