std :: stod抛出应为有效字符串的out_of_range错误 [英] std::stod throws out_of_range error for a string that should be valid

查看:450
本文介绍了std :: stod抛出应为有效字符串的out_of_range错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#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将由于序列化双精度值而产生,但stod无法将其反序列化。这里发生了什么?可能的最小两倍可能在10 ^ -324附近。

"7.63918e-313" will result from serializing a double, but stod cannot deserialize it. What's going on here? The smallest possible double is supposedly around 10^−324.

stdlib中是否有一对函数可以可靠地从字符串化来回映射双精度?

Is there a pair of functions somewhere in the stdlib that can reliably map doubles back and forth from stringification? Shouldn't there be?

地块变厚了。我们有两个奇怪的发现。

The plot thickens. We have two bizarre observations.


  • std :: numeric_limits< double> :: min()也不能通过stod解析。

  • std::numeric_limits<double>::min() cannot be parsed by stod either.

std :: numeric_limits< double> :: min()不是最小的两倍。我们的双精度数较小,我发现只要将min进行除法就可以得到较小的双精度数,因此这并不是说我的双精度异常或任何其他原因 https://onlinegdb.com/rJvilljQz

std::numeric_limits<double>::min() is not the minimum double. Our double is smaller, and I find we can get smaller doubles by simply dividing min, so it's not that my double is anomalous or anything https://onlinegdb.com/rJvilljQz

我非常担心。

推荐答案

转换 7.63918e-313



C ++标准允许将字符串转换为 double 报告结果下溢,即使结果在次标准范围内也可以表示。

Converting "7.63918e-313"

The C++ standard allows conversions of strings to double to report underflow if the result is in the subnormal range even though it is representable.

7.63918•10 < sup> -313 在 double 的范围内,但在次标准范围内。 C ++标准说 stod 调用 strtod ,然后根据C标准定义 strtod 。 C标准表示 strtod 可能会下溢,并表示:如果数学结果的大小如此之小以至于无法表示数学结果,则结果会下溢,舍入错误,在指定类型的对象中。这很尴尬,但它指的是遇到次标准值时发生的舍入误差。 (次标准值比标准值要有更大的相对误差,因此,其四舍五入误差可能会说是非常大的。)

7.63918•10-313 is within the range of double, but it is in the subnormal range. The C++ standard says stod calls strtod and then defers to the C standard to define strtod. The C standard indicates that strtod may underflow, about which it says "The result underflows if the magnitude of the mathematical result is so small that the mathematical result cannot be represented, without extraordinary roundoff error, in an object of the specified type." That is awkward phrasing, but it refers to the rounding errors that occur when subnormal values are encountered. (Subnormal values are subject to larger relative errors than normal values, so their rounding errors might be said to be extraordinary.)

因此,C ++允许C ++实现

Thus, a C++ implementation is allowed by the C++ standard to underflow for subnormal values even though they are representable.

关于您的观察, std :: numeric_limits< double> :: min()均无法解析(我想您是说它也报告下溢),这可能是是由于您将 std :: numeric_limits< double> :: min()转换为包含十进制数字的字符串,而该十进制数字不是精确的表示形式 std :: numeric_limits< double> :: min()的值。如果将其四舍五入,则它会小于 min(),因此也处于非正常范围内。因此,尝试将该十进制数字转换回 double 可能会正确地报告它低于正常范围。

Regarding your observation that std::numeric_limits<double>::min() "cannot be parsed" either (I presume you mean it also reports underflow), this may be due to the fact that you converted std::numeric_limits<double>::min() to a string containing a decimal numeral, and that decimal numeral was not an exact representation of std::numeric_limits<double>::min(). If it was rounded down, it is slightly less than min(), and hence it is also in the subnormal range. Thus, attempting to convert that decimal numeral back to a double may correctly report it is below the normal range.

关于您观察到的 std :: numeric_limits< double> :: min( )不是最小的 double ,这是正确的。 C ++标准将 std :: numeric_limits< double> :: min()指定为最小正标准值。

Regarding your observation that std::numeric_limits<double>::min() is not the minimum double, that is correct. std::numeric_limits<double>::min() is specified by the C++ standard to be the minimum positive normal value. There may be subnormal values below it.

对于IEEE-754 64位二进制文​​件浮点数,正常范围是2 -1022 到2 1024 -2 971 。在此范围内,每个数字都用一个符号前导号(浮点表示形式的小数部分)表示,该符号前导1位,后跟52个附加位,因此在将此范围内的任何实数四舍五入到整数时都会发生错误。最接近的可表示值最多是前导位的位置值的2 -53

For IEEE-754 64-bit binary floating-point, the normal range is from 2-1022 to 21024-2971. Within this range, every number is represented with a signficand (the fraction portion of the floating-point representation) that has a leading 1 bit followed by 52 additional bits, and so the error that occurs when rounding any real number in this range to the nearest representable value is at most 2-53 times the position value of the leading bit.

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

In additional to this normal range, there is a subnormal range from 2-1074 to 2-1022-2-1074. In this interval, the exponent part of the floating-point format has reached its smallest value and cannot be decreased any more. To represent smaller and smaller numbers in this interval, the significand is reduced below the normal minimum of 1. It starts with a 0 and is followed by 52 additional bits. In this interval, the error that occurs when rounding a real number to the nearest representable value may be larger than 2-53 times the position value of the leading bit. Since the exponent cannot be decreased any further, numbers in this interval have increasing numbers of leading 0 bits as they get smaller and smaller. Thus the relative errors involved with using these numbers grows.

出于某种原因,C ++表示实现可能会报告在此间隔内发生下溢。 (IEEE-754标准以复杂的方式定义下溢,并且还允许实现一些选择。)

For whatever reasons, the C++ has said that implementations may report underflow in this interval. (The IEEE-754 standard defines underflow in complicated ways and also allows implementations some choices.)

这篇关于std :: stod抛出应为有效字符串的out_of_range错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆