【问题标题】:Is stof, strtof deterministic?stof, strtof 是确定性的吗?
【发布时间】:2016-10-06 16:14:18
【问题描述】:

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

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

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

【问题讨论】:

  • 不是 100% 确定。 stof 在内部调用 strtod,所以我不知道这是否会有所作为。在 C++17 中,它会在内部调用 strtof,所以它应该得到保证。
  • 我也不是 100% 确定。我认为这个问题需要一个标准参考。 @SnoopDog 的回答应该被视为只是猜想。

标签: c++ floating-point deterministic


【解决方案1】:

The C11 standard, in 7.22.1.3p9,对 C 的 strtof/strtod/strtold 有这样的说法(这应该是 C++ 版本在下面使用的,至少从 cppreference 来看):

如果主题序列具有十进制形式且最多为DECIMAL_DIG(在<float.h> 中定义)有效数字,则结果应正确四舍五入。

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

【讨论】:

  • 您确定两者都使用strtof 吗? cplusplus 提到 stof 使用 strtod 但没有类似 stof
  • @tobi303 cppreference 提到 strtof 作为“基础函数”(在脚注中;但没有更好的参考)。
  • @mindriot stof 调用 strtod 直到 C++17 它将调用 strtof
【解决方案2】:

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 确实为 double rounding 打开了潜力。例如。如果str = "1.0000000596046448",那么最接近的float(假设IEEE754算术)是1.0000001f,而最接近的double正好在1.0f1.0000001f之间的中间,因此后续转换为float将向下舍入到1.0f

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-17
    • 2011-12-31
    • 2012-05-13
    • 2016-10-20
    • 1970-01-01
    • 1970-01-01
    • 2016-05-12
    相关资源
    最近更新 更多