formatnum.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:3k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // formatnum.cpp
  2. // 
  3. // Copyright (C) 2003, Chris Laurel <claurel@shatters.net>
  4. //
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. #include <cmath>
  10. #include <cstdio>
  11. #include <cstring>
  12. #include <climits>
  13. #include "formatnum.h"
  14. // HACK: MS Visual C++ has _snprintf declared in stdio.h but not snprintf
  15. #ifdef _WIN32
  16. #define snprintf _snprintf
  17. #endif
  18. FormattedNumber::FormattedNumber(double v,
  19.                                  unsigned int _precision,
  20.                                  unsigned int _flags) :
  21.     value(v),
  22.     precision(_precision),
  23.     flags(_flags)
  24. {
  25. }
  26. double FormattedNumber::getValue() const
  27. {
  28.     return value;
  29. }
  30. double FormattedNumber::getRoundedValue() const
  31. {
  32.     if (flags & SignificantDigits)
  33.     {
  34.         if (value == 0.0)
  35.         {
  36.             return 0.0;
  37.         }
  38.         else
  39.         {
  40.             double m = pow(10.0, floor(log10(fabs(value))) - precision + 1);
  41.             return floor(value / m + 0.5) * m;
  42.         }
  43.     }
  44.     else
  45.     {
  46.         return value;
  47.     }
  48. }
  49. std::ostream& operator<<(std::ostream& out, const FormattedNumber& num)
  50. {
  51.     char fmt[32];
  52.     char buf[32];
  53.     char obuf[64];
  54.     double value = num.getRoundedValue();
  55.     char *decimal_point = localeconv()->decimal_point;
  56.     char *thousands_sep = localeconv()->thousands_sep;
  57.     char *grouping = localeconv()->grouping;
  58.     memset(obuf, 0, sizeof(obuf));
  59.     if (num.flags & FormattedNumber::SignificantDigits)
  60.     {
  61.         if (value == 0.0)
  62.         {
  63.             snprintf(fmt, sizeof(fmt)/sizeof(char), "%%.%df", 5);
  64.         }
  65.         else
  66.         {
  67.             int fmtPrecision = (int) log10(fabs(value)) - num.precision + 1;
  68.             if (fabs(value) < 1.0)
  69.                 fmtPrecision--;
  70.             snprintf(fmt, sizeof(fmt)/sizeof(char), "%%.%df", fmtPrecision > 0 ? 0 : -fmtPrecision);
  71.         }
  72.     }
  73.     else
  74.     {
  75.         snprintf(fmt, sizeof(fmt)/sizeof(char), "%%.%df", num.precision);
  76.     }
  77.     snprintf(buf, sizeof(buf)/sizeof(char), fmt, value);
  78.     if (num.flags & FormattedNumber::GroupThousands)
  79.     {
  80.         const char* decimalPosition = strstr(buf, decimal_point);
  81.         int j = sizeof(obuf) - 1;
  82.         int i = strlen(buf);
  83.         int digitCount = 0;
  84.         if (decimalPosition != NULL)
  85.         {
  86.             int len = strlen(decimalPosition);
  87.             j -= len;
  88.             i -= len;
  89.             memcpy(obuf + j, decimalPosition, len);
  90.             --i;
  91.             --j;
  92.         }
  93.         
  94.         const char *g = grouping;
  95.         bool does_grouping = *g != 0;
  96.         while (i >= 0)
  97.         {
  98.             if (isdigit(buf[i]))
  99.             {
  100.                 if (does_grouping && *g != CHAR_MAX)
  101.                 {
  102.                     if (digitCount == *g)
  103.                     {
  104.                         const char *c, *ts = thousands_sep;
  105.                         for (c = ts + strlen(ts) - 1; c >= ts; c--)
  106.                         {
  107.                             obuf[j] = *c;
  108.                             j--;
  109.                         }
  110.                         if (*(g+1) != 0) g += 1;
  111.                         digitCount = 0;
  112.                     }
  113.                 }
  114.                 digitCount++;
  115.             }
  116.             obuf[j] = buf[i];
  117.             j--;
  118.             i--;
  119.         }
  120.         out << (obuf + (j + 1));
  121.     }
  122.     else
  123.     {
  124.         out << buf;
  125.     }
  126.     return out;
  127. }