dirk/C++/c++/print-float
Weingarten, 10-02-16
print-float – Normal versus Exponent Formatting
Somebody told me, that the processing of floating point values is rather slow concerning the scanning as well as the formatted output.
One reason might be the localization effort but system issues are also imaginable.
However, localization is rather undesired for text file readers, in opposition to performance which is a must.
Some weeks ago, I proved this for scanning (i.e. strtod etc.)
I was really surprised and impressed about the speed-up of my own implementation compared to the naïve approach:
char *localeOld = setlocale(LC_NUMERIC, "C");
value = strtod(text);
setlocale(LC_NUMERIC, localeOld);
|
My own implementation is rather straight forward but the measured speed-up (on MS Windows) was a factor of 60 ... 100!
May be, I publish this code one day (currently part of my professional work) together with a test run on Linux.
However, multiple source codes are easy to find in the W3 using the search engine of your choice.
This time, I planned to replace the formatted output.
My first concern was: how to choose normal or scientific output.
I could have search the W3 but decided to make a sample – a rather non-scientific but really quick solution.
Thus, I implemented a console application printing the values of in-/de-creasing numbers in a loop.
Source Code
print-float.cc |
/** @file sample for formatted output of floating point
*
* Last CVS checkin:
* $Date: $
* $Author: scheff $
*/
/**************************************************************************/
// standard C/C++ header:
#include <iostream>
#include <string>
/**************************************************************************/
using namespace std;
/** waits for user confirm.
*
* @param action text with next action
*/
static void pause(const char *action)
{
cout << "Press [ENTER] to " << action << ": " << flush;
string str; getline(cin, str);
}
/** provides the main function of application.
*
* @param argc number of command line arguments
* @param argv pointer to array of pointers to strings with command line
* arguments
* @return 0 ... application exited regularly\n
* else ... execution of application aborted
*/
int main(int argc, char *argv[])
{
pause("start");
// print floating points as is
double value1 = 1.0, value2 = 1.0; int i = 0;
for (;;) {
cout << '\t' << value1 << '\t' << value2 << endl;
{ double value = value1; value1 *= 0.1; if (value == value1) break; }
{ double value = value2; value2 *= 10.0; if (value == value2) break; }
if (++i == 10) { pause("continue"); i = 0; }
}
// done
pause("finish");
return 0;
}
|
I compiled this sample on Linux with:
> g++ -o print-float print-float.cc↵
> ↵
> ↵
> ↵
> uname -a↵
Linux pc60 2.6.18.2-34-default #1 SMP Mon Nov 27 11:46:27 UTC 2006 i686 i686 i38
6 GNU/Linux
> g++ -v↵
Using built-in specs.
Target: i586-suse-linux
Configured with: ../configure --enable-threads=posix --prefix=/usr --with-local-
prefix=/usr/local --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/us
r/lib --libexecdir=/usr/lib --enable-languages=c,c++,objc,fortran,obj-c++,java,a
da --enable-checking=release --with-gxx-include-dir=/usr/include/c++/4.1.2 --ena
ble-ssp --disable-libssp --disable-libgcj --with-slibdir=/lib --with-system-zlib
--enable-shared --enable-__cxa_atexit --enable-libstdcxx-allocator=new --progra
m-suffix=-4.1 --enable-version-specific-runtime-libs --without-system-libunwind
--with-cpu=generic --host=i586-suse-linux
Thread model: posix
gcc version 4.1.2 20061115 (prerelease) (SUSE Linux)
>
|
Output
This was a test run on MS Windows XP:
| Console: |
Press [ENTER] to start: ↵
1 1
0.1 10
0.01 100
0.001 1000
0.0001 10000
1e-005 100000
1e-006 1e+006
1e-007 1e+007
1e-008 1e+008
1e-009 1e+009
Press [ENTER] to continue: ^C
|
This was a test run on Linux:
| Console: |
Press [ENTER] to start: ↵
1 1
0.1 10
0.01 100
0.001 1000
0.0001 10000
1e-05 100000
1e-06 1e+06
1e-07 1e+07
1e-08 1e+08
1e-09 1e+09
Press [ENTER] to continue: ^C
|
Conclusion
The switch from common to scientific formatting occurs at the same powers of 10.
Next time, I will implement a binary search to find the exact values...
Until now, the resulting code would be:
// decide format: common or scientific
if (value >= 1E6 || value <= -1E6
|| value <= 1E-5 && value >= -1E-5) { // scientific format
} else { // common format
}
|
Files
dirk/C++/c++/print-float
Last modified: Sun Feb 28 13:16:40 2010