Example #1
0
    /**
     * Format a number supplied as a decimal
     *
     * @param dval the decimal value
     * @param fsb the FastStringBuffer to contain the result
     */
    private void formatDecimal(BigDecimal dval, FastStringBuffer fsb) {
      dval = dval.setScale(maxFractionPartSize, BigDecimal.ROUND_HALF_EVEN);
      DecimalValue.decimalToString(dval, fsb);

      int point = fsb.indexOf('.');
      int intDigits;
      if (point >= 0) {
        int zz = maxFractionPartSize - minFractionPartSize;
        while (zz > 0) {
          if (fsb.charAt(fsb.length() - 1) == '0') {
            fsb.setLength(fsb.length() - 1);
            zz--;
          } else {
            break;
          }
        }
        intDigits = point;
        if (fsb.charAt(fsb.length() - 1) == '.') {
          fsb.setLength(fsb.length() - 1);
        }
      } else {
        intDigits = fsb.length();
        if (minFractionPartSize > 0) {
          fsb.append('.');
          for (int i = 0; i < minFractionPartSize; i++) {
            fsb.append('0');
          }
        }
      }
      if (minWholePartSize == 0 && intDigits == 1 && fsb.charAt(0) == '0') {
        fsb.removeCharAt(0);
      } else {
        fsb.prependRepeated('0', minWholePartSize - intDigits);
      }
    }
Example #2
0
 /**
  * Convert a double to a BigDecimal. In general there will be several BigDecimal values that are
  * equal to the supplied value, and the one we want to choose is the one with fewest non-zero
  * digits. The algorithm used is rather pragmatic: look for a string of zeroes or nines, try
  * rounding the number down or up as approriate, then convert the adjusted value to a double to
  * see if it's equal to the original: if not, use the original value unchanged.
  *
  * @param value the double to be converted
  * @param precision 2 for a double, 1 for a float
  * @return the result of conversion to a double
  */
 public static BigDecimal adjustToDecimal(double value, int precision) {
   final String zeros = (precision == 1 ? "00000" : "000000000");
   final String nines = (precision == 1 ? "99999" : "999999999");
   BigDecimal initial = new BigDecimal(value);
   BigDecimal trial = null;
   FastStringBuffer fsb = new FastStringBuffer(20);
   DecimalValue.decimalToString(initial, fsb);
   String s = fsb.toString();
   int start = (s.charAt(0) == '-' ? 1 : 0);
   int p = s.indexOf(".");
   int i = s.lastIndexOf(zeros);
   if (i > 0) {
     if (p < 0 || i < p) {
       // we're in the integer part
       // try replacing all following digits with zeros and seeing if we get the same double back
       FastStringBuffer sb = new FastStringBuffer(s.length());
       sb.append(s.substring(0, i));
       for (int n = i; n < s.length(); n++) {
         sb.append(s.charAt(n) == '.' ? '.' : '0');
       }
       trial = new BigDecimal(sb.toString());
     } else {
       // we're in the fractional part
       // try truncating the number before the zeros and seeing if we get the same double back
       trial = new BigDecimal(s.substring(0, i));
     }
   } else {
     i = s.indexOf(nines);
     if (i >= 0) {
       if (i == start) {
         // number starts with 99999... or -99999. Try rounding up to 100000.. or -100000...
         FastStringBuffer sb = new FastStringBuffer(s.length() + 1);
         if (start == 1) {
           sb.append('-');
         }
         sb.append('1');
         for (int n = start; n < s.length(); n++) {
           sb.append(s.charAt(n) == '.' ? '.' : '0');
         }
         trial = new BigDecimal(sb.toString());
       } else {
         // try rounding up
         while (i >= 0 && (s.charAt(i) == '9' || s.charAt(i) == '.')) {
           i--;
         }
         if (i < 0 || s.charAt(i) == '-') {
           return initial; // can't happen: we've already handled numbers starting 99999..
         } else if (p < 0 || i < p) {
           // we're in the integer part
           FastStringBuffer sb = new FastStringBuffer(s.length());
           sb.append(s.substring(0, i));
           sb.append((char) ((int) s.charAt(i) + 1));
           for (int n = i; n < s.length(); n++) {
             sb.append(s.charAt(n) == '.' ? '.' : '0');
           }
           trial = new BigDecimal(sb.toString());
         } else {
           // we're in the fractional part - can ignore following digits
           String s2 = s.substring(0, i) + (char) ((int) s.charAt(i) + 1);
           trial = new BigDecimal(s2);
         }
       }
     }
   }
   if (trial != null
       && (precision == 1 ? trial.floatValue() == value : trial.doubleValue() == value)) {
     return trial;
   } else {
     return initial;
   }
 }