C ++:将字符串转换为双精度

时间:2019-03-17 13:13:38

标签: 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";

3 个答案:

答案 0 :(得分:1)

  

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

这是不可能的,除非您针对一个其双浮点表示形式可以表示该数字的系统。

您的CPU可能使用的普遍存在的IEEE 754 binary64标准中没有0.03456的表示形式。最接近的可表示数字是3.45600000000000004418687638008E-2。无论您使用strtodstod还是字符流来转换字符串,这就是您应该获得的数字。

  

有没有一种方法可以实现?

要在浮点不能表示该数字的系统上精确表示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

答案 1 :(得分:0)

假设您希望小数点后的位数为小数点后的总位数的一部分,则可以执行以下操作

  1. 计算小数点后的位数。设为n
  2. 现在就像您一样将字符串转换为十进制。设为d
  3. 现在,如果您想保留50%个小数位,可以使用一个古老的技巧

double d_new = round(d * pow(10.0, 5)) / pow(10.0, 5)。假设精度达到5位数字。

  

注意:与其他答案不同,这里您将舍入原始十进制数。不只是将四舍五入的小数点打印到stdout。

示例:

#include<stdio.h>
#include<cmath>

int main(){
    double a = 0.0345555566;
    double b = 0.00883342;
    double c = 0.2111907;

    double a_new = round(a * pow(10.0, 5)) / pow(10.0, 5);
    double b_new = round(b * pow(10.0, 4)) / pow(10.0, 4);
    double c_new = round(c * pow(10.0, 3)) / pow(10.0, 3);

    printf("%.10f\n", a_new);
    printf("%.10f\n", b_new);
    printf("%.10f\n", c_new);
}

查看50%的精度

结果:

  

0.0345600000

  0.0088000000

  0.2110000000

答案 2 :(得分:-1)

使用字符串流代替strtod:

#include <iostream>
#include <sstream>

double convert(std::string string) {
    std::stringstream s(string);
    double ret = 0;
    s >> ret;
    return ret;
}

int main() {
    std::cerr << convert("0.03456") << std::endl;
    std::cerr << convert("0.1889") << std::endl;
    std::cerr << convert("0.00883342") << std::endl;
    std::cerr << convert("0.2111907") << std::endl;
    std::cerr << convert("3.0045") << std::endl;
    std::cerr << convert("1.45") << std::endl;
    return 0;

}

在我的系统上,这给出了:

0.03456
0.1889
0.00883342
0.211191
3.0045
1.45

正如一些评论中指出的那样,并非所有数字都可以用双精度表示。但是您列出的大多数都可以。