繁体   English   中英

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

[英]C++ : Converting String to Double

这是用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";

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

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

CPU可能使用的普遍存在的IEEE 754二进制64标准中没有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. 计算小数点后的位数。 设为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

使用字符串流代替的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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM