C++ 字符串到浮点的转换?
我想知道什么样的算法可以用来将类似“4.72”的内容转换成浮点数据类型,等于C++ 字符串到浮点的转换?,c++,c,C++,C,我想知道什么样的算法可以用来将类似“4.72”的内容转换成浮点数据类型,等于 float x = 4.72; atof()函数可能会有所帮助。 对于C和C99朋友strtof()和strtold()(同一链接上的说明)已经实现了该算法 如果您在编写自己的代码时遇到问题,请发布您的代码和相关的具体问题。scanf,operator>对于istreams和strof将是明显的选择 还有atof,但与atoi一样,它无法告诉您输入中有错误,因此通常最好避免两者。您可以使用boost:lexical\
float x = 4.72;
atof()函数可能会有所帮助。
对于C
和C99
朋友strtof()
和strtold()
(同一链接上的说明)已经实现了该算法
如果您在编写自己的代码时遇到问题,请发布您的代码和相关的具体问题。
scanf
,operator>
对于istreams和strof
将是明显的选择
还有
atof
,但与atoi
一样,它无法告诉您输入中有错误,因此通常最好避免两者。您可以使用boost:lexical\u cast
< C++ > P > >可以使用:
对于C++,这是我使用的算法:
bool FromString(const string& str, double& number) {
std::istringstream i(str);
if (!(i >> number)) {
// Number conversion failed
return false;
}
return true;
}
我在过去使用atof()进行转换,但我发现这有问题,因为如果无法进行有效转换,它将返回(0.0)。因此,您不知道它是否失败并返回零,或者字符串中是否实际包含“0”。From:“stringstream
提供了一个界面,可以像处理输入/输出流一样处理字符串。”
您可以使用字符串初始化stringstream
,然后使用operator>
从stringstream
读取浮点值,就像使用cin
一样
以下是一个例子:
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
int main() {
string s = "4.72";
stringstream sstrm(s);
float x;
sstrm >> x;
cout << x << endl;
}
#包括
#包括
#包括
使用名称空间std;
int main(){
字符串s=“4.72”;
stringstream sstrm(s);
浮动x;
sstrm>>x;
cout我假设您想要的是一个实际的算法,而不是一个已经实现了它的库函数。我没有时间编写和测试实际的代码,但下面是我要做的:
将用作累加器的浮点初始化为0
找出小数点在字符串中的位置,这将让您知道每个数字的“列”是什么(即100s、10s、1s、1/10等)
从字符串的开头开始
取该数字,转换为整数(通常通过从ASCII值中减去0x30完成)
将该值乘以place列(对于示例中的第一个数字,即4*1==4,对于下一个数字,即7*0.1==0.7)
将结果添加到累加器中
对每个剩余数字重复步骤4
累加器现在包含您的结果
由于在循环的每次迭代中,基数10和基数2之间的转换是舍入的,因此您从该算法得到的结果可能不是与原始值最接近的二进制表示形式。不过,我真的不知道有什么好方法可以改进它……也许其他人可以插话。正如您要求的alg一样算法,而不是方法,以下是我对一个简单算法(以及C语言实现)的解释:
初始化4个整数变量,一个用于点之前的值,一个用于点之后的部分,一个用于尾数的幂,一个用于符号。比如说,f,m,d,sign=1
首先在开头查找+或-符号。如果没有符号字符或+符号,则继续。如果第一个字符是-,则符号=-1
然后,将一个整数值读入f,直到出现一个.或空字符
如果你以一个点字符结束,那么开始读取尾数部分,如前一步中的m。但这次也用每个数字乘以d乘以10
最后,返回符号*(f+(float)m/d)。强制转换确保以浮点进行除法,并且表达式的类型为float
我想,阅读代码可能更容易。下面是代码:
float atof(char *s)
{
int f, m, sign, d=1;
f = m = 0;
sign = (s[0] == '-') ? -1 : 1;
if (s[0] == '-' || s[0] == '+') s++;
for (; *s != '.' && *s; s++) {
f = (*s-'0') + f*10;
}
if (*s == '.')
for (++s; *s; s++) {
m = (*s-'0') + m*10;
d *= 10;
}
return sign*(f + (float)m/d);
}
你真的想要一个算法,还是一个已经编写好的函数?strtof
而不是strtod
,因为提问者想要一个float
而不是double
。对了,斯蒂芬,谢谢(但是strtof和strtold是“新的”)。后期编辑。使用strtod
并将结果转换为float
(隐式或通过强制转换)与strtof
@R.一样好,而且更便于携带。它不是很“一样好”;它有可能导致双舍入,从而使其精度稍微降低(如果您使用的是float
,您可能并不关心这一点),而且速度可能慢得多(取决于您的c库)。对于大多数用途,可移植性压倒了这些顾虑,但并非所有用途都如此。别忘了处理像-1.2e-3
这样的数字。这种转换充满了微妙之处和边缘情况。要做到正确,绝非易事。如果你必须自己实现它,请在你能想到的每个边缘情况下测试它。然后担心。And也不要忘记NaN和INF的情况。@RBerteig:如果这是我的字符串转换函数,我可以简单地声明负数和科学符号无效;)但事实上,是的,它需要比我写的更复杂。我想OP只是想简单地概括一下这种转换是如何可能的。当然,为了简化问题,你可以决定应该处理什么的合理范围。我只是想补充一点,将文本转换为浮点可能需要处理比“4.72”更复杂的情况。C89兼容strtod()的一个实现< /代码>我看到的是大约80行稠密且几乎没有注释的代码。例如:“RBTETEIG:确实如此。谢谢。”用简单的部分解释源代码的清晰和清晰。别忘了处理<代码> -1E-6<代码>、<代码> .3E+ 5 、<代码> + 2、E-4< /代码>和类似的内容,或者明确指定您不允许使用此表单。请考虑HANDLIN。G变形数字更好(尝试“ABC”作为输入)。也考虑处理Na和Fin。C99要求<代码> SCAFF()>代码>能够精确恢复由<代码> Primff()/<代码>打印的值,即使楠和Fin。C89不,但其<代码> SttoDo()/代码>处理T。
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
int main() {
string s = "4.72";
stringstream sstrm(s);
float x;
sstrm >> x;
cout << x << endl;
}
float atof(char *s)
{
int f, m, sign, d=1;
f = m = 0;
sign = (s[0] == '-') ? -1 : 1;
if (s[0] == '-' || s[0] == '+') s++;
for (; *s != '.' && *s; s++) {
f = (*s-'0') + f*10;
}
if (*s == '.')
for (++s; *s; s++) {
m = (*s-'0') + m*10;
d *= 10;
}
return sign*(f + (float)m/d);
}