I'm wondering what sort of algorithm could be used to take something like "4.72" into a float data type, equal to
float x = 4.72;
I'm wondering what sort of algorithm could be used to take something like "4.72" into a float data type, equal to
float x = 4.72;
For C++ you can use boost::lexical_cast:
std::string str( "4.72" );
float x = boost::lexical_cast< float >( str );
For C you can use sscanf:
char str[]= "4.72";
float x;
sscanf( str, "%f", &x );
For C++ This is the algorithm I use:
bool FromString(const string& str, double& number) {
std::istringstream i(str);
if (!(i >> number)) {
// Number conversion failed
return false;
}
return true;
}
I used atof() in the past for the conversion, but I found this problematic because if no valid conversion can be made, it will return (0.0). So, you would not know if it failed and returned zero, or if the string actually had "0" in it.
For C strtod() and C99 friends strtof() and strtold() (description on same link) already have that algorithm implemented.
If you are having problems writing your own, post your code and specific questions about it.
strtof instead of strtod, since the questioner wants a float instead of a double.strtod and converting the result to float (implicitly or with a cast) is just as good and a lot more portable than strtof.float, you probably don't care about this), and can be much slower (depending on your c library). For most uses, these concerns are trumped by portability, but not for all uses.As you've asked for an algorithm, not a method, here is my explanation for a simple algorithm (and an implementation in C):
I guess, reading the code might be easier. So here is the code:
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);
}
-1e-6, .3e+5, +2.e-4 and similar, or specify explicitly that you don't allow this form. Consider handling malformed numbers better (try "ABC" as input). Also consider handling NaN and INF. C99 requires that scanf() be capable of exactly recovering a value printed by printf(), even NaN and INF. C89 does not, but its strtod() does handle the E notation.You can use boost:lexical_cast
http://www.boost.org/doc/libs/1_44_0/libs/conversion/lexical_cast.htm
I assume you want an actual algorithm, not a library function that already does it. I don't have time to write and test actual code, but here is what I would do:
Due to the roundoff of converting between base 10 and base 2 in every iteration of this loop, the result you get from this algorithm may not be the closest possible binary representation to the original value. I don't really know of a good way to improve it though... perhaps someone else can chime in with that.
-1.2e-3. This conversion is fraught with subtleties and edge cases. It is by no means easy to get right. If you must implement it yourself, test the crap out of it at every edge case you can dream up. And then worry. And don't forget about NaN and INF cases either.strtod() I've seen is about 80 lines of dense and hardly commented code, for example.The atof() function can be helpful. http://www.cplusplus.com/reference/clibrary/cstdlib/atof/
strtod() over atof() since you have better chance of finding out that something went wrong when you get unexpected input with strtod().From cplusplus.com: "stringstream provides an interface to manipulate strings as if they were input/output streams."
You can initialize a stringstream with your string then read a float from the stringstream using operator>> just like you would with cin.
Here is an example:
#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;
}