Floating point to string conversion
I'm writing a scripting language in c++.
I have a custom String class and I decided to write my own number to string and string to number conversion routines.
Most people will probably advice me to use standard STL string and conversion routines. I need the custom string class; it's a base for a token class. I'm not in a hurry with this project and I thought it would be nice to encapsulate this functionality into my string class. Besides, standard functions for these tasks are slow.
The problem is, I'm not very familiar with floating point standards and it's a real pain in the butt to convert a float or a double to a string. Which standards do pc/windows systems use? IEEE 754? How portable will my code be?
Should I forget these and just use snprintf or something similar?
Way to go dude! Making your own number conversion routines is awesomely cool!
If you are planning to make a completely custom system and arent worrying about outputting data to other modules I would suggest you create your own number format. Otherwize I would guess that all windows systems have the same number format - the macs might be the same but with switched endian, I have never had to worry about this myself tho so I would wait for more opinions if I were you.
Edit: if u dont want to worry about speed you could always just read in the digits with decimal place, then use the arithetical processor to multiply with the correct power of ten and add it all up to a float. Hmm, I guess there isn't much time to gain by doing it any other way tho... (i.e. inline asm :P)
If you are planning to make a completely custom system and arent worrying about outputting data to other modules I would suggest you create your own number format. Otherwize I would guess that all windows systems have the same number format - the macs might be the same but with switched endian, I have never had to worry about this myself tho so I would wait for more opinions if I were you.
Edit: if u dont want to worry about speed you could always just read in the digits with decimal place, then use the arithetical processor to multiply with the correct power of ten and add it all up to a float. Hmm, I guess there isn't much time to gain by doing it any other way tho... (i.e. inline asm :P)
Don't waste your time re-inventing the wheel. If you are using C, snprintf and strtod should work for you. If you are using C++, almost all the stream I/O classes can handle it for you.
On another point: you said "Besides, standard functions for these tasks are slow." I believe that is unfounded. Have you compared profile results of optimized versions your routines with those of the C++ IO stream equivalents, and considering the robustness, determined that their versions perform worse than yours? Don't make unfounded conclusions about performance. Always measure before complaining about speed.
On another point: you said "Besides, standard functions for these tasks are slow." I believe that is unfounded. Have you compared profile results of optimized versions your routines with those of the C++ IO stream equivalents, and considering the robustness, determined that their versions perform worse than yours? Don't make unfounded conclusions about performance. Always measure before complaining about speed.
Yep I have made comparisons. Number conversion library functions are usually slow. For example my integer to string conversion is about 2 times as fast as the best library versions.
Thanks for the tips. I'm coming to the conclusion that this is a waste of time :D. I'll use some standard functions. Sure it's slower, but the code is much cleaner, which is a benefit too. And string handling functions aren't very time critical in any case.
Thanks for the tips. I'm coming to the conclusion that this is a waste of time :D. I'll use some standard functions. Sure it's slower, but the code is much cleaner, which is a benefit too. And string handling functions aren't very time critical in any case.
I read your message and coded up a quick test for converting from double to a std::string. It has a couple of problems with precision, so I added the #define, though it doesn't do rounding now. I know it can be improved upon, but perhaps this will give you some idea? If this is what you're looking for, by all means, use it. If nothing else this was an exercise for me [smile].
#include <iostream>#include <string>#include <math.h>#define precision 10std::string dtos(double input);std::string itos(int input);int main(){ std::cout<< dtos(-397.14154973156); return 0;}std::string dtos(double input){std::string result;double temp = input;result += itos(int(temp));result += ".";if(int(temp) < 0){ temp *= -1;}temp -= int(temp);for(int i=1; i <= precision; i++){temp *= 10;result += itos(int(temp));temp -= int(temp);}return result;}std::string itos(int input){ char temp[255]; itoa(input, temp, 10); std::string newInt = temp; return newInt;}
For something simple, caffineaddict posted a good sample. I would just not use the itoa and itos functions as they're not standard.
The standard c/c++ routines are probably faster, though, so I would use those. Plus they take into account rounding(I think???)
The standard c/c++ routines are probably faster, though, so I would use those. Plus they take into account rounding(I think???)
itoa() is not standard C++ or C89, which poses a significant problem for a lot of programmers.
C++ allows such things with standardized code, with stringstreams as mentioned above:
[Edited by - taby on May 25, 2006 6:55:16 PM]
C++ allows such things with standardized code, with stringstreams as mentioned above:
#include <sstream>using std::ostringstream;#include <iomanip>using std::setprecision;#include <ios>using std::ios_base;#include <iostream>using std::cout;using std::endl;int main(void){ float f = 0.0; ostringstream oss; oss.precision(4); f = 1.0e-4; oss << "Fixed version of " << typeid(f).name() << " f: " << f; cout << oss.str() << endl; oss.str(""); // clear ostringstream f = 1.0e-5; oss << "Scientific version of " << typeid(f).name() << " f: " << f; cout << oss.str() << endl; oss.str(""); // clear ostringstream f = 1.0001e-4; oss << "Truncated version of " << typeid(f).name() << " f: " << f; cout << oss.str() << endl; oss.str(""); // clear ostringstream return 0;}
[Edited by - taby on May 25, 2006 6:55:16 PM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement