0

高速ダブルスキャンが必要な問題の解決策を最適化しようとしています。標準入力からdoubleを読み取る関数を実装しようとしましたが、失敗しました。誰かがこれを効率的に実装する簡単なコードを教えてもらえますか?前もって感謝します。

これが私の試みであることに注意してください。これにはいくつかの問題があるようです。

#include <stdio.h>
#include <stdlib.h>

inline double getDouble(FILE *f = stdin) {
    char tmp[20], ch;
    bool seen = false;
    double sign = 1.0;
    short index = 0;

    while((ch = getc(stdin)) != EOF) {
        if(ch == '-') {
            sign = -1.0;
            continue;
        }
        if(ch == ' ' || ch == '\n') {
            if(seen) break;
        } else {
            seen = true;
            tmp[index++] = ch;
        }
    }
    return sign * (double)atof(tmp);
}

int main() {
    int n;
    scanf("%d", &n);

    double *d = new double[n];

    for(int i=0; i<n; ++i) {
        d[i] = getDouble();
    }

    for(int i=0; i<n; ++i) {
        printf("%.5lf\n", d[i]);
    }

    return 0;
}

入力:

16
-2 -1 -4 -5
1 1 1 1
1.233 -435 -2.44
3
2 3 42 4 
4

2 に答える 2

1
#include <stdio.h>
#include <stdlib.h>

inline double getDouble(FILE *f = stdin) {
    double d;
    scanf("%lf", &d);
    return d;
}

int main() {
    int n;
    scanf("%d", &n);

    double *d = new double[n];

    for(int i=0; i<n; ++i) {
        d[i] = getDouble();
    }

    for(int i=0; i<n; ++i) {
        printf("%.5lf\n", d[i]);
    }

    return 0;
}

編集:これは確かにいくらか速くなる可能性があります、私は以下が2〜3倍速いと推定します、それはあなたの入力を通過しますが、かなりの仮定を取ります、テストサンプルの外での保証はありません:)

inline double getDouble(FILE *f = stdin) {
    char ch;
    bool seen = false;
    bool sign = false;
    char values[10];
    double result =0.;
    bool beforeDot = true;
    int beforeLength = 0;
    double multiplier;

    while((ch = getc(stdin)) != EOF) {
        if(ch == '-') {
            sign = true;
            continue;
        }
        if(ch == ' ' || ch == '\n') {
            if(seen) break;
            continue;
        }
        if(ch == '.') {
            beforeDot = false;
            multiplier = 1.;
            while(beforeLength) {
                result += (double)(values[--beforeLength] - '0') * multiplier;
                multiplier *= 10.;
            }
            multiplier = 10.;
        }
        else {
            if(!beforeDot)
            {
                result += double(ch - '0') / multiplier;
                multiplier *= 10.;
            } else {
                values[beforeLength++] = ch;
            }
            seen = true;
        }
    }
    if(beforeDot) {
        multiplier = 1;
        while(beforeLength) {
            result += (double)(values[--beforeLength] - '0') * multiplier;
            multiplier *= 10.;
        }
    }

    if(sign) result *= -1.;

    return result;
}
于 2013-01-15T19:14:46.610 に答える
0

私の最初のテストは次のようになります。

inline double getDouble(std::istream& in = std::cin)
{
     double value;
     if (!(in >> value)) {throw "Error";}
     return value;
}

これが十分に速くない場合(そしてその時だけ)、私は試してみます:

inline double getDouble(FILE *f = stdin)
{
    double value;
    if ((scanf(f, "%e", &value) != 1) { throw "Error";}
    return value;
}

これが十分に速くない場合(そしてそのときのみ)、私は試してみます:
そして、人々がそれを最適化するために多くの時間を持っていたので、これがscanf()よりも速いとは思えません

inline double getDouble(FILE *f = stdin)
{
     int c;

     // Ignore leading white space
     while((c = getc(f) != EOF) && std::is_space(c)) {/*Loop*/}

     // Only dealing with reals that look like this:
     // [+|-]?[0-9]+(.[0-9]*)?
     // or
     // [+|-]?([0-9]*)?.[0-9]+

     // Deal with sign
     c=getc(f);
     char sign = 1;
     if ((c == '-') || (c == '+'))
     {
         if (c == '-') { sign = -1;}
         c=getc(f);
     }

     int  top
     int  bot;
     // See if next character is a '.'
     if (c == '.')
     {
         top = 0;
         bot = readDigits(f, c, true);
     }
     else
     {
         top = readDigits(f, c, true);
         bot = 0;
         if (c == '.')
         {
             c = getc(f);
             bot = readDigits(f, c, false);
         }
     }
     //put back the last unused character
     putc(c, f);

     // calculate the result.
     double result = sign * (top*1.0 + (bot*1.0/getSizeofBot(bot)));
     return result;
}
int readDigits(FILE* f, int& c, bool digitRequired)
{
     // c contains the first character.
     // It should contain the last character read on exit.

     // If digitRequired is true it is an exception to not 
     // find a digit, Other wise it is OK.
     if ((digitRequired) && !std::is_digit(c))
     {    throw "Error";
     }
     // Read an integer and return its value.
     int value = 0;

     while(std::is_digit(c))
     {
         value = value * 10 + (c - '0');
         c = getc(f);
     }
     return value;
}
于 2013-01-15T18:53:51.533 に答える