首页 > 解决方案 > C++:将字符串转换为双精度

问题描述

它是用 Visual Studio 2015 编写的 C++ 代码。如下所示,

LPSTR *endPtr;
string strDouble = "0.03456";
double valDouble = strtod(strDouble.c_str(), &endPtr);

现在 valDouble 的输出“0.0345555566”,类似这样。

我希望valDouble中的值恰好是“0.03456”。

基本上“0.0345555566”的值需要四舍五入才能说“0.03456”。

有没有办法可以实现?

顺便说一句,strDouble中的值一直在变化。所以不可能将精度设置为 5 或类似的值。下面是一些用于strDouble的示例。

string strDouble = "0.1889";
string strDouble = "0.00883342";
string strDouble = "0.2111907";
string strDouble = "3.0045";
string strDouble = "1.45";

标签: c++

解决方案


我希望 valDouble 中的值恰好是“0.03456”。

这是不可能的,除非您的目标是一个双浮点表示可以表示该数字的系统。

您的 CPU 可能使用的无处不在的 IEEE 754 binary64 标准中不存在 0.03456 的表示。最接近的可表示数字是 3.45600000000000004418687638008E-2。strtod无论您使用,stod还是字符流来转换字符串,这都是您应该得到的数字。

有没有办法可以实现?

为了在浮点不能表示该数字的系统上准确表示 0.03456,您必须使用整数来表示该数字。您可以使用整数实现任意精度算术、定点算术或十进制浮点数。

基本上值......需要四舍五入才能说“0.03456”。

将非精确浮点数转换为字符串时,可以对输出进行四舍五入:

std::cout << std::setprecision(4) << 0.03456;

顺便说一句,strDouble 中的值一直在变化。所以不可能将精度设置为 5 或类似的值。

然后,您必须记录输入字符串中的有效位数,以便在输出中使用相同的精度。

这是一个用于此目的的示例函数:

template<class Range>
auto get_precision(const Range& r)
{
    auto is_significant = [](auto c) {
        return std::isdigit(c) && c != '0';
    };
    auto first = std::find_if(std:: begin(r), std:: end(r), is_significant);
    auto last  = std::find_if(std::rbegin(r), std::rend(r), is_significant).base();
    return std::count_if(first, last, [](auto c) {
        return std::isdigit(c);
    });
}

// demo
std::cout << get_precision("0.03456"); // 4

推荐阅读