Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

formatnum.cpp

Go to the documentation of this file.
00001 // formatnum.cpp
00002 // 
00003 // Copyright (C) 2003, Chris Laurel <claurel@shatters.net>
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 
00010 #include <cmath>
00011 #include <cstdio>
00012 #include <string>
00013 #include "formatnum.h"
00014 
00015 
00016 FormattedNumber::FormattedNumber(double v,
00017                                  unsigned int _precision,
00018                                  unsigned int _flags) :
00019     value(v),
00020     precision(_precision),
00021     flags(_flags)
00022 {
00023 }
00024 
00025 
00026 double FormattedNumber::getValue() const
00027 {
00028     return value;
00029 }
00030 
00031 
00032 double FormattedNumber::getRoundedValue() const
00033 {
00034     if (flags & SignificantDigits)
00035     {
00036         if (value == 0.0)
00037         {
00038             return 0.0;
00039         }
00040         else
00041         {
00042             double m = pow(10.0, floor(log10(fabs(value))) - precision + 1);
00043             return floor(value / m + 0.5) * m;
00044         }
00045     }
00046     else
00047     {
00048         return value;
00049     }
00050 }
00051 
00052 
00053 std::ostream& operator<<(std::ostream& out, const FormattedNumber& num)
00054 {
00055     char fmt[32];
00056     char buf[32];
00057     char obuf[64];
00058     double value = num.getRoundedValue();
00059     char *decimal_point = localeconv()->decimal_point;
00060     char *thousands_sep = localeconv()->thousands_sep;
00061     char *grouping = localeconv()->grouping;
00062 
00063     memset(obuf, 0, sizeof(obuf));
00064 
00065     if (num.flags & FormattedNumber::SignificantDigits)
00066     {
00067         if (value == 0.0)
00068         {
00069             sprintf(fmt, "%%.%df", 5);
00070         }
00071         else
00072         {
00073             int fmtPrecision = (int) log10(fabs(value)) - num.precision + 1;
00074             if (fabs(value) < 1.0)
00075                 fmtPrecision--;
00076             sprintf(fmt, "%%.%df", fmtPrecision > 0 ? 0 : -fmtPrecision);
00077         }
00078     }
00079     else
00080     {
00081         sprintf(fmt, "%%.%df", num.precision);
00082     }
00083 
00084     sprintf(buf, fmt, value);
00085 
00086     if (num.flags & FormattedNumber::GroupThousands)
00087     {
00088         const char* decimalPosition = strstr(buf, decimal_point);
00089         int j = sizeof(obuf) - 1;
00090         int i = strlen(buf);
00091         int digitCount = 0;
00092         if (decimalPosition != NULL)
00093         {
00094             int len = strlen(decimalPosition);
00095             j -= len;
00096             i -= len;
00097             memcpy(obuf + j, decimalPosition, len);
00098             --i;
00099             --j;
00100         }
00101         
00102         const char *g = grouping;
00103         bool does_grouping = *g != 0;
00104         while (i >= 0)
00105         {
00106             if (isdigit(buf[i]))
00107             {
00108                 if (does_grouping && *g != CHAR_MAX)
00109                 {
00110                     if (digitCount == *g)
00111                     {
00112                         const char *c, *ts = thousands_sep;
00113                         for (c = ts + strlen(ts) - 1; c >= ts; c--)
00114                         {
00115                             obuf[j] = *c;
00116                             j--;
00117                         }
00118                         if (*(g+1) != 0) g += 1;
00119                         digitCount = 0;
00120                     }
00121                 }
00122                 digitCount++;
00123             }
00124 
00125             obuf[j] = buf[i];
00126 
00127             j--;
00128             i--;
00129         }
00130 
00131         out << (obuf + (j + 1));
00132     }
00133     else
00134     {
00135         out << buf;
00136     }
00137 
00138     return out;
00139 }

Generated on Sat Jan 14 22:30:32 2006 for Celestia by  doxygen 1.4.1