gpt4 book ai didi

c++ - std::stod 为应该有效的字符串抛出 out_of_range 错误

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:13:07 25 4
gpt4 key购买 nike

#include <iostream>
#include <cmath>
#include <sstream>
using namespace std;

int main(){
stringstream ss;
double ad = 7.63918e-313;
ss << ad;
cout<<ss.str()<<endl;
//you will see that the above double is valid, and maps to the specified string

//but stod cannot map it back
stod("7.63918e-313");
//terminate called after throwing an instance of 'std::out_of_range'
}

在这里运行:https://onlinegdb.com/Sy1MT1iQM

“7.63918e-313”将由序列化一个 double 值产生,但 stod 不能反序列化它。这里发生了什么?最小的双倍数应该是 10^−324 左右。

stdlib 中是否有一对函数可以可靠地从字符串化来回映射 double ?不应该有吗?

情节变厚了。我们有两个奇怪的观察结果。

  • std::numeric_limits<double>::min() stod 也无法解析。

  • std::numeric_limits<double>::min()不是最小加倍。我们的双更小,我发现我们可以通过简单地除以最小值来得到更小的 double ,所以这并不是说我的 double 有异常或其他什么https://onlinegdb.com/rJvilljQz

我很担心。

最佳答案

转换“7.63918e-313”

C++ 标准允许将字符串转换为 double如果结果在低于正常范围内,即使它是可表示的,也报告下溢。

7.63918•10-313double范围内, 但在正常范围内。 C++ 标准说 stod电话 strtod然后按照 C 标准来定义 strtod . C标准表示strtod可能下溢,关于它说“如果数学结果的量级太小以至于无法在指定类型的对象中表示数学结果,没有异常舍入误差,结果就会下溢。”这是一个笨拙的措辞,但它指的是遇到次正规值时发生的舍入误差。 (低于正常值的相对误差比正常值大,因此它们的舍入误差可以说是非常大的。)

因此,C++ 标准允许 C++ 实现对次正规值进行下溢,即使它们是可表示的。

转换 std::numeric_limits::min()

关于您的观察 std::numeric_limits<double>::min() “也无法解析”(我猜你的意思是它也报告下溢),这可能是因为你转换了 std::numeric_limits<double>::min()到包含十进制数字的字符串,并且该十进制数字不是 std::numeric_limits<double>::min() 的精确表示.如果向下舍入,则略小于 min()。 ,因此它也在低于正常范围内。因此,试图将该十进制数字转换回 double可能会正确报告它低于正常范围。

std::numeric_limits::min() 不是最小双数

关于您的观察 std::numeric_limits<double>::min()不是最小值double , 那是对的。 std::numeric_limits<double>::min()由 C++ 标准指定为最小正正常值。它下面可能有低于正常值。

正常值和低于正常值

对于 IEEE-754 64 位二进制 float ,正常范围是从 2-1022 到 21024-2971 .在这个范围内,每个数字都用一个符号(浮点表示的小数部分)表示,它有一个前导 1 位,后面跟着 52 个额外的位,所以当这个范围内的任何实数四舍五入到最近的可表示值最多是前导位位置值的 2-53 倍。

除了这个正常范围之外,还有一个从 2-1074 到 2-1022-2-1074 的低于正常范围。在这个区间内,浮点格式的指数部分已经达到最小值,不能再减少了。为了表示此区间中越来越小的数字,有效数减少到正常最小值 1 以下。它以 0 开头,后面跟着 52 个附加位。在此区间内,将实数舍入到最接近的可表示值时发生的误差可能大于前导位位置值的 2-53 倍。由于指数不能进一步减少,因此该区间中的数字随着变得越来越小而增加前导 0 位的数量。因此,使用这些数字所涉及的相对错误会增加。

无论出于何种原因,C++ 都表示实现可能会在此时间间隔内报告下溢。 (IEEE-754 标准以复杂的方式定义了下溢,也允许实现一些选择。)

关于c++ - std::stod 为应该有效的字符串抛出 out_of_range 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48086830/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com