2015-07-10 84 views

回答

1

使用您提供的链接的想法,我写了自己的快速浮动数字输入技术。下面的代码(包括main()进行测试):

#include <stdio.h> 
#define gc getchar_unlocked 

int neg; 

int scandigits(double *x, int div) { 
    register int c = gc(); 
    register double pow10 = 1; 
    if (x == NULL) { 
    return -1; 
    } 
    *x = 0; 
    while ((c < '0' || c > '9') && c != '-') { 
    c = gc(); 
    } 
    if (c == '-') { 
    neg = 1; 
    c = gc(); 
    } 
    while (!(c < '0' || c > '9')) { 
    *x *= 10; 
    *x += (c - '0'); 
    pow10 *= 10; 
    c = gc(); 
    } 
    if (neg) 
    *x = -*x; 
    if (div) 
    *x /= pow10; 
    return c; 
} 

void scandouble(double *x) { 
    double left, right = 0; 
    if (x == NULL) { 
    return; 
    } 
    neg = 0; 
    int ret = scandigits(&left, 0); 
    if (ret == '.') 
    scandigits(&right, 1); 
    *x = left + right; 
} 

int main() { 
    double d; 
    scandouble(&d); 
    printf("%f", d); 
    return 0; 
} 

注:在一般情况下,最有竞争力的比赛编码不需要快速IO。相反,他们需要更好的算法等。但是,在一些极少数情况下,您需要快速IO才能产生最后0.01s以使您的代码被接受。我只会建议在这种情况下使用这种欺骗(这就是我所说的)。

+0

做了一些测试:当'-'在像'-0.001286'之前的'.'之前得到错误的符号。除此之外,大约52%的时间都像'atof()'那样工作。当它不同时,错误大约是3位的精度。最坏的情况下,大约5位。 (53)。当然,不处理指数符号,INF,NAN。 TBD在'-0.0'和子法线之上。数字靠近'DBL_MAX'失败。 – chux

+0

更正了符号问题。问题存在于范围开放间隔(-1.0,0.0)内的数字。由于代码是用于竞争性编码(其具有非常固定的格式输入并且不需要真正的错误检查),所以不需要处理指数符号,INF,NAN等。 –

0

经常使用整数运算比double要快。下面使用整数数学来组成有效数和可选的指数。

double getdouble(void) { 
    int ch = getchar(); 
    int sign = ch; 
    if (sign == '-' || sign == '+') { 
    ch = getchar(); 
    } 
    long long sum = 0; 
    int digit_count = 0; 
    int dp_offset = -1; 
    int power10 = 0; 
    int dp = '.'; 
    for (;;) { 
    while (ch >= '0' && ch <= '9') { 
     digit_count++; 
     if (sum < LLONG_MAX/10) { 
     sum = sum * 10 + ch - '0'; 
     } else { 
     power10++; 
     } 
     ch = getchar(); 
    } 
    if (ch == dp) { 
     dp = '0'; 
     dp_offset = digit_count; 
     ch = getchar(); 
    } else { 
     break; 
    } 
    } 
    if (dp_offset >= 0) { 
    power10 -= digit_count - dp_offset; 
    } 
    if (ch == 'e' || ch == 'E') { 
    ch = getchar(); 
    int esign = ch; 
    if (esign == '-' || esign == '+') { 
     ch = getchar(); 
    } 
    int expo = 0; 
    while (ch >= '0' && ch <= '9') { 
     expo = expo * 10 + ch - '0'; 
     ch = getchar(); 
    } 
    if (esign == '-') expo = -expo; 
    power10 += expo; 
    } 
    double y = sum; 
    if (power10) { 
    // combine these 2 steps for speed with `pow(10,power10)`. 
    // leave separate for better handling of very large/very tiny numbers 
    y *= pow(5, power10); // 
    y = ldexp(y, power10); 
    } 
    if (sign == '-') y = -y; 
    return y; 
} 

atof()的答案相同86%的时间。
出错时,出现1位错误。
更糟的情况:1位。
句柄指数表示法和子法线,-0.0。
不处理NAN,INF。
返回INF +/-DBL_MAX,适用于所有较小的值。