我实现了一个函数StringToDouble将字符串转换为double,但是当我用相同的字符串测试我的函数和标准strtod函数时,结果不同,我不知道为什么会发生这种情况,是不是用double做算术时精度有问题?以及如何修复我的函数,使其生成与 strtod 相同的结果?谢谢。这是我实现的 StringToDouble
bool StringToDouble(const char *p, double &num) {
int frac;
double sign, value, scale;
bool canConvert = false;
if (p == NULL || *p == 0) {
num = 0;
return false;
}
// Skip leading white space, if any.
while (white_space(*p)) {
p += 1;
}
// Get sign, if any.
sign = 1.0;
if (*p == '-') {
sign = -1.0;
p += 1;
} else if (*p == '+') {
p += 1;
}
if (valid_digit(*p)) canConvert = true;
// Get digits before decimal point or exponent, if any.
for (value = 0.0; valid_digit(*p); p += 1) {
value = value * 10.0 + (*p - '0');
}
// Get digits after decimal point, if any.
if (*p == '.') {
double pow10 = 10.0;
p += 1;
if (valid_digit(*p)) canConvert = true;
while (valid_digit(*p)) {
value += (*p - '0') / pow10;
pow10 *= 10.0;
p += 1;
}
}
// Handle exponent, if any.
frac = 0;
scale = 1.0;
if ((*p == 'e') || (*p == 'E')) {
unsigned int expon;
// Get sign of exponent, if any.
p += 1;
if (*p == '-') {
frac = 1;
p += 1;
} else if (*p == '+') {
p += 1;
}
// Get digits of exponent, if any.
for (expon = 0; valid_digit(*p); p += 1) {
expon = expon * 10 + (*p - '0');
}
if (expon > 308) expon = 308;
// Calculate scaling factor.
while (expon >= 50) {
scale *= 1E50;
expon -= 50;
}
while (expon >= 8) {
scale *= 1E8;
expon -= 8;
}
while (expon > 0) {
scale *= 10.0;
expon -= 1;
}
}
// Return signed and scaled floating point result.
if (!canConvert) {
num = 0;
return false;
} else {
num = sign * (frac ? (value / scale) : (value * scale));
return true;
}
}
这是我用于测试的代码
const char *p = "3e+100";
double d;
StringToDouble(p, d);
double dd = strtod(p, nullptr);
if (d == dd) {
cout.precision(17);
cout << dd << endl
<< d;
} else {
cout.precision(17);
cout << "not equal\n";
cout << dd << endl
<< d;
}
输出是
not equal
2.9999999999999999e+100
3.0000000000000006e+100
我还测试了其他字符串,有些用strtod得到相同的结果,有些不是,所有带指数的情况都得到不同的结果。