简体   繁体   English

用C ++解析float函数

[英]Parsing float function in C++

My question is regarding the solution posted by 6502 on [ c++ stringstream is too slow, how to speed up? 我的问题是关于6502发布的解决方案[ c ++ stringstream太慢,如何加速? Parsing Float method posted by him is fast but its not giving correct result on large double values. 他发布的解析Float方法很快,但是它没有给出大的double值的正确结果。

Input: 输入:

132.12345645645645 132.12345645645645

Output: 输出:

132.123 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;
}

I want to know is there any way to change this function to get correct result. 我想知道是否有任何方法可以更改此功能以获得正确的结果。

If you're printing the result with cout, make sure you set the necessary precision: 如果您使用cout打印结果,请确保设置必要的精度:

cout.precision(20);

live example 实例

However as you noted a simpler method would be: 但是,正如您所指出的更简单的方法是:

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;
 }

Notice: due to roundoff errors, exceeding with the number of digits might not yield 100% expected results on the rightmost part. 注意:由于舍入错误,超过数字位数可能不会在最右边的部分产生100%的预期结果。

The scaling for the digits after the decimal point is significantly worse than useless. 小数点后的数字缩放明显比无用的差。

Multiplying by 0.1 is a mistake ... not least because 0.1 is not represented exactly in binary floating point. 乘以0.1是一个错误 ...不仅仅是因为0.1没有在二进制浮点中精确表示。 So going round in a loop, repeatedly multiplying by 0.1 is accumulating more and more error. 因此,在循环中循环,重复乘以0.1会累积越来越多的错误。

For big numbers, when multiplying the number so far by 10, and adding the next digit value, you are going to accumulate more errors :-( 对于大数字,当将数字乘以10并添加下一个数字值时,您将累积更多错误:-(

The trick is to accumulate the digits as an unsigned long long (assuming that's at least 64 bits), ignoring the . 诀窍是将数字累加为unsigned long long (假设至少为64位),忽略了. but counting the number of digits after it. 但计算它之后的位数。 When you have all the digits, float the integer and then divide by the required power of 10. Now you have at most one rounding (in the float, if you have more than 53 bits of value) and a second in the division. 当你有所有的数字时,浮动整数然后除以所需的10的幂。现在你最多有一个舍入(浮点数,如果你有超过53位的值)和除法中的第二个。 But, things can get complicated... if you have a number whose value exceeds what you can fit in an unsigned long long , you need to stop adding digits (and round)... if that happens before the . 但是,事情可能会变得复杂......如果你的数字值超过你在unsigned long long整数中的数量,你需要停止添加数字(和圆形)......如果在数字之前发生这种情况. , you need to count digits up to it, and then multiply by a power of 10. ,你需要计算数字,然后乘以10的幂。

NB : decimal to binary floating point conversion is hard in the general case. 注意 :在一般情况下,十进制到二进制浮点转换很难 If you are converting numbers without exponents, and the number of digits is reasonable, it's not too bad. 如果你要转换没有指数的数字,并且位数是合理的,那也不算太糟糕。 The problem that bites you is how to create large powers of 10 to multiply/divide by, without introducing (unacceptable) errors. 咬你的问题是如何创建10的大功率乘以/除以,而不会引入(不可接受的)错误。

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

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