你可以使用stringstream安全地双向转换吗?

W. *_*man 5 c++ formatting stringstream

我有这种情况,使用stringstream将double转换为字符串.现在,我必须在其他地方取回该值(不,我无法访问原始的double),所以我必须解析格式化的字符串.

当然,我也可以用字符串流来读它,但这样安全吗?对所有价值观而言,它总能奏效吗?

std::ostringstream doubleToString;
double myDouble = 3.14;
doubleToString << myDouble;
std::string convertedDouble = doubleToString.str();

std::istringstream stringToDouble(convertedDouble);
double newDouble;
stringToDouble >> newDouble;
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,myDouble总是等于newDouble吗?

注意:边际差异(0.00000000001)不是我关注的问题.

Edw*_*ard 4

不,它并不总是有效。您可以使用代码的这个小修改来向自己证明这一点:

#include <sstream>
#include <iostream>
#include <string>
#include <cassert>

int main()
{
    std::ostringstream doubleToString;
    double zero = 0;
    double myDouble = 3.14/zero;
    doubleToString << myDouble;
    std::string convertedDouble = doubleToString.str();
    std::cout << "convertedDouble = " << convertedDouble << std::endl;

    std::istringstream stringToDouble(convertedDouble);
    double newDouble;
    stringToDouble >> newDouble;
    std::cout << "newDouble = " << newDouble << std::endl;
    assert(newDouble == myDouble);
}
Run Code Online (Sandbox Code Playgroud)

当我在我的机器上运行此代码时,我得到以下输出:

convertedDouble = inf
newDouble = 0
xlat: xlat.cpp:19: int main(): Assertion `newDouble == myDouble' failed.
Aborted (core dumped)
Run Code Online (Sandbox Code Playgroud)

更新:

请注意,如果您始终以特定机器上可表示浮点数范围内的双精度数(即std::numeric_limits<double>::min() <= x <= std::numeric_limits<double>::max())开始,则仍然无法保证。作为一个例子,尝试使用上面的代码double myDouble = 1/3.0;。问题在于将 发送double到字符串时的精度。我们可以尝试通过修改代码来解决这个问题:

doubleToString << 
    std::setprecision(std::numeric_limits<double>::digits10) << myDouble;
Run Code Online (Sandbox Code Playgroud)

这具有将精度设置为整数值所需的小数位数的效果,该整数值始终能够在double. 然而,它仍然不适用于所有双精度值!

double myDouble = pow(1/3.0, 300);
Run Code Online (Sandbox Code Playgroud)

该值将导致断言触发。原因是digits10只代表浮点数的尾数部分,并不代表指数。在这里完全迂腐,我们可以将正确的值设置为:

constexpr int dblprecision = std::numeric_limits<double>::digits10 
        + ceil(log10(std::numeric_limits<double>::max_exponent10));
doubleToString << std::setprecision(dblprecision) << myDouble;
Run Code Online (Sandbox Code Playgroud)

请注意,这仅在双精度到字符串转换方向上需要,而在其他方向上则不需要。

因此,了解输入值必须在指示的范围内,并且假设您设置了转换为字符串的精度,我认为这将始终导致原始双精度,假设编译器或库的实现中没有错误。