解析c++中的float函数

Parsing float function in C++

本文关键字:函数 float 中的 c++ 解析      更新时间:2023-10-16

我的问题是关于6502上发布的解决方案[c++ stringstream太慢,如何加速?]解析Float方法由他发布是快速的,但它不能给出正确的结果大双精度值。

输入:

132.12345645645645
输出:

132.123
double parseFloat(const std::string& input){
    const char *p = input.c_str();
    if (!*p || *p == '?')
        return NAN_D;
    int s = 1;
    while (*p == ' ') p++;
    if (*p == '-') {
        s = -1; p++;
    }
    double acc = 0;
    while (*p >= '0' && *p <= '9')
        acc = acc * 10 + *p++ - '0';
    if (*p == '.') {
        double k = 0.1;
        p++;
        while (*p >= '0' && *p <= '9') {
            acc += (*p++ - '0') * k;
            k *= 0.1;
        }
    }
    if (*p) die("Invalid numeric format");
    return s * acc;
}

我想知道是否有办法改变这个函数来得到正确的结果。

如果使用cout打印结果,请确保设置了必要的精度:

cout.precision(20);

生活例子

然而,正如你所注意到的,一个更简单的方法是:

double string_to_double( const std::string& s )
 {
   std::istringstream i(s);
   double x;
   if (!(i >> x))
     return std::numeric_limits<double>::quiet_NaN(); // Or anything you prefer
   return x;
 }

注意:由于舍入错误,超过最右边的位数可能无法产生100%的预期结果

对小数点后的数字进行缩放是非常糟糕的。

乘以0.1是一个错误…尤其是因为0.1不能精确地用二进制浮点数表示。因此,在循环中,反复乘以0.1会积累越来越多的误差。

对于大数,当将目前的数字乘以10,并加上下一个数字的值时,您将累积更多的错误:-(

技巧是将这些数字累加为unsigned long long(假设至少有64位),忽略.,但计算它之后的位数。当你有了所有的数字,浮点整数,然后除以所需的10的幂。现在你最多有一次四舍五入(在浮点数中,如果你有超过53位的值),除法中有第二次。但是,事情可能会变得复杂……如果你有一个数字的值超过了unsigned long long可以容纳的范围,你需要停止添加数字(和四舍五入)…如果发生在.之前,您需要数到它的数字,然后乘以10的幂。

NB:一般情况下,十进制到二进制的浮点转换是硬的。如果您正在转换没有指数的数字,并且位数是合理的,那么它不是太糟糕。困扰您的问题是如何在不引入(不可接受的)错误的情况下创建10的大幂来乘/除。