我正在尝试优化我的问题解决方案,这需要快速双重扫描。我试图实现一个从标准输入中读取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
答案 0 :(得分: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;
}
答案 1 :(得分: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;
}