我的问题是关于 6502 发布的解决方案 [c++ stringstream is too slow, how to speed up? 他发布的解析Float方法很快,但是它没有给出大的双值的正确结果。
输入:
132.12345645645645
输出:
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;
}
我想知道有没有办法改变这个功能以获得正确的结果。
答案 0 :(得分:8)
如果您使用cout打印结果,请确保设置必要的精度:
cout.precision(20);
然而,正如您所指出的更简单的方法是:
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;
}
注意:由于舍入错误,超过数字位数可能不会在最右边的部分产生100%的预期结果。
答案 1 :(得分:1)
小数点后的数字缩放明显比无用的差。
乘以0.1
是一个错误 ......尤其是因为0.1
没有完全用二进制浮点表示。因此,在循环中循环,重复乘以0.1
会累积越来越多的错误。
对于大数字,当将数字乘以10并添加下一个数字值时,您将累积更多错误: - (
诀窍是将数字累加为unsigned long long
(假设至少为64位),忽略.
但计算其后的位数。当你有所有的数字时,浮动整数然后除以所需的10的幂。现在你最多有一个舍入(浮点数,如果你有超过53位的值)和除法中的第二个。但是,事情会变得复杂......如果你的数字值超过你在unsigned long long
中可以容纳的数字,你需要停止添加数字(和圆形)......如果这个数字发生在{{1}之前你需要计算数字,然后乘以10的幂。
NB :一般情况下,十进制到二进制浮点转换为硬。如果你要转换没有指数的数字,并且位数是合理的,那也不算太糟糕。咬你的问题是如何创建10的大功率乘以/除以,而不会引入(不可接受的)错误。