Java Code Examples for java.math.BigDecimal#movePointLeft()

The following examples show how to use java.math.BigDecimal#movePointLeft() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ValueLinkApi.java    From scipio-erp with Apache License 2.0 5 votes vote down vote up
/**
 * Returns a BigDecimal from a ValueLink formatted amount String
 * @param amount The ValueLink formatted amount String
 * @return BigDecimal object
 */
public BigDecimal getAmount(String amount) {
    if (amount == null) {
        return BigDecimal.ZERO;
    }
    BigDecimal amountBd = new BigDecimal(amount);
    return amountBd.movePointLeft(2);
}
 
Example 2
Source File: CurrencyMapper.java    From catatumbo with Apache License 2.0 5 votes vote down vote up
@Override
public Object toModel(Value<?> input) {
  if (input instanceof NullValue) {
    return null;
  }
  BigDecimal n = new BigDecimal(((LongValue) input).get());
  n = n.movePointLeft(fractionalDigits);
  return n;
}
 
Example 3
Source File: PurapAccountingServiceImpl.java    From kfs with GNU Affero General Public License v3.0 5 votes vote down vote up
/**
 * gets the lowest possible number for rounding, it works for ROUND_HALF_UP
 *
 * @return a BigDecimal representing the lowest possible number for rounding
 */
protected BigDecimal getLowestPossibleRoundUpNumber() {
    BigDecimal startingDigit = new BigDecimal(0.5);
    if (SCALE != 0) {
        startingDigit = startingDigit.movePointLeft(SCALE);
    }
    return startingDigit;
}
 
Example 4
Source File: DecimalUtility.java    From Bats with Apache License 2.0 4 votes vote down vote up
/**
 * Function converts the BigDecimal and stores it in out internal sparse representation
 */
public static void getSparseFromBigDecimal(BigDecimal input, ByteBuf data, int startIndex, int scale, int nDecimalDigits) {

  // Initialize the buffer
  data.setZero(startIndex, nDecimalDigits * INTEGER_SIZE);

  boolean sign = false;

  if (input.signum() == -1) {
    // negative input
    sign = true;
    input = input.abs();
  }

  // Truncate the input as per the scale provided
  input = input.setScale(scale, BigDecimal.ROUND_HALF_UP);

  // Separate out the integer part
  BigDecimal integerPart = input.setScale(0, BigDecimal.ROUND_DOWN);

  int destIndex = nDecimalDigits - roundUp(scale) - 1;

  // we use base 1 billion integer digits for out internal representation
  BigDecimal base = new BigDecimal(DIGITS_BASE);

  while (integerPart.compareTo(BigDecimal.ZERO) == 1) {
    // store the modulo as the integer value
    data.setInt(startIndex + destIndex * INTEGER_SIZE, integerPart.remainder(base).intValue());
    destIndex--;
    // Divide by base 1 billion
    integerPart = integerPart.divide(base, BigDecimal.ROUND_DOWN).setScale(0, BigDecimal.ROUND_DOWN);
  }

  /* Sparse representation contains padding of additional zeroes
   * so each digit contains MAX_DIGITS for ease of arithmetic
   */
  int actualDigits = scale % MAX_DIGITS;
  if (actualDigits != 0) {
    // Pad additional zeroes
    scale = scale + MAX_DIGITS - actualDigits;
    input = input.setScale(scale, BigDecimal.ROUND_DOWN);
  }

  //separate out the fractional part
  BigDecimal fractionalPart = input.remainder(BigDecimal.ONE).movePointRight(scale);

  destIndex = nDecimalDigits - 1;

  while (scale > 0) {
    // Get next set of MAX_DIGITS (9) store it in the DrillBuf
    fractionalPart = fractionalPart.movePointLeft(MAX_DIGITS);
    BigDecimal temp = fractionalPart.remainder(BigDecimal.ONE);

    data.setInt(startIndex + destIndex * INTEGER_SIZE, temp.unscaledValue().intValue());
    destIndex--;

    fractionalPart = fractionalPart.setScale(0, BigDecimal.ROUND_DOWN);
    scale -= MAX_DIGITS;
  }

  // Set the negative sign
  if (sign) {
    data.setInt(startIndex, data.getInt(startIndex) | 0x80000000);
  }
}
 
Example 5
Source File: LvmUtils.java    From linstor-server with GNU General Public License v3.0 4 votes vote down vote up
public static Map<String, Long> getThinFreeSize(ExtCmdFactory extCmdFactory, Set<String> volumeGroups)
    throws StorageException
{
    final int expectedColums = 3;

    final Map<String, Long> result = new HashMap<>();

    OutputData output = execWithRetry(
        extCmdFactory,
        volumeGroups,
        config -> LvmCommands.getVgThinFreeSize(extCmdFactory.create(), volumeGroups, config)
    );
    final String stdOut = new String(output.stdoutData);
    final String[] lines = stdOut.split("\n");

    for (final String line : lines)
    {
        final String[] data = line.trim().split(DELIMITER);
        if (data.length == expectedColums)
        {
            try
            {
                BigDecimal thinPoolSizeBytes = StorageUtils.parseDecimal(data[1].trim());

                BigDecimal dataPercent = StorageUtils.parseDecimal(data[2].trim());
                BigDecimal dataFraction = dataPercent.movePointLeft(2);
                BigDecimal freeFraction = dataFraction.negate().add(BigDecimal.valueOf(1L));

                BigInteger freeBytes = thinPoolSizeBytes.multiply(freeFraction).toBigInteger();
                long freeSpace = SizeConv.convert(freeBytes, SizeUnit.UNIT_B, SizeUnit.UNIT_KiB).longValueExact();

                result.put(
                    data[0],
                    freeSpace
                );
            }
            catch (NumberFormatException nfExc)
            {
                throw new StorageException(
                    "Unable to parse free thin sizes",
                    "Numeric value to parse: '" + data[1] + "'",
                    null,
                    null,
                    "External command: " + String.join(" ", output.executedCommand),
                    nfExc
                    );
            }
        }
        else
        {
            throw new StorageException(
                "Unable to parse free thin sizes",
                "Expected " + expectedColums + " columns, but got " + data.length,
                "Failed to parse line: " + line,
                null,
                "External command: " + String.join(" ", output.executedCommand)
                );
        }
    }
    return result;
}
 
Example 6
Source File: DecimalHelper.java    From dremio-oss with Apache License 2.0 4 votes vote down vote up
public static void getSparseFromBigDecimal(BigDecimal input, ByteBuf data, int startIndex,
                                           int scale, int nDecimalDigits) {

  // Initialize the buffer
  for (int i = 0; i < nDecimalDigits; i++) {
    data.setInt(startIndex + (i * INTEGER_SIZE), 0);
  }

  boolean sign = false;

  if (input.signum() == -1) {
    // negative input
    sign = true;
    input = input.abs();
  }

  // Truncate the input as per the scale provided
  input = input.setScale(scale, BigDecimal.ROUND_HALF_UP);

  // Separate out the integer part
  BigDecimal integerPart = input.setScale(0, BigDecimal.ROUND_DOWN);

  int destIndex = nDecimalDigits - roundUp(scale) - 1;

  while (integerPart.compareTo(BigDecimal.ZERO) > 0) {
    // store the modulo as the integer value
    data.setInt(startIndex + (destIndex * INTEGER_SIZE), (integerPart.remainder(BASE_BIGDECIMAL)).intValue());
    destIndex--;
    // Divide by base 1 billion
    integerPart = (integerPart.divide(BASE_BIGDECIMAL)).setScale(0, BigDecimal.ROUND_DOWN);
  }

  /* Sparse representation contains padding of additional zeroes
   * so each digit contains MAX_DIGITS for ease of arithmetic
   */
  int actualDigits = scale % MAX_DIGITS;
  if (actualDigits != 0) {
    // Pad additional zeroes
    scale = scale + (MAX_DIGITS - actualDigits);
    input = input.setScale(scale, BigDecimal.ROUND_DOWN);
  }

  //separate out the fractional part
  BigDecimal fractionalPart = input.remainder(BigDecimal.ONE).movePointRight(scale);

  destIndex = nDecimalDigits - 1;

  while (scale > 0) {
    // Get next set of MAX_DIGITS (9) store it in the DrillBuf
    fractionalPart = fractionalPart.movePointLeft(MAX_DIGITS);
    BigDecimal temp = fractionalPart.remainder(BigDecimal.ONE);

    data.setInt(startIndex + (destIndex * INTEGER_SIZE), (temp.unscaledValue().intValue()));
    destIndex--;

    fractionalPart = fractionalPart.setScale(0, BigDecimal.ROUND_DOWN);
    scale -= MAX_DIGITS;
  }

  // Set the negative sign
  if (sign) {
    data.setInt(startIndex, data.getInt(startIndex) | 0x80000000);
  }
}
 
Example 7
Source File: RV_RETURN_VALUE_IGNORED_BigDecimal.java    From spotbugs with GNU Lesser General Public License v2.1 4 votes vote down vote up
@ExpectWarning("RV_RETURN_VALUE_IGNORED")
void bug2(BigDecimal any1, int anyInt) {
    any1.movePointLeft(anyInt);
}
 
Example 8
Source File: FractionProcessor.java    From Time4A with Apache License 2.0 4 votes vote down vote up
@Override
public void parse(
    CharSequence text,
    ParseLog status,
    AttributeQuery attributes,
    ParsedEntity<?> parsedResult,
    boolean quickPath
) {

    Leniency leniency = (quickPath ? this.lenientMode : attributes.get(Attributes.LENIENCY, Leniency.SMART));
    int effectiveMin = 0;
    int effectiveMax = 9;

    if (!leniency.isLax() || this.fixedWidth) {
        effectiveMin = this.minDigits;
        effectiveMax = this.maxDigits;
    }

    int len = text.length();

    if (status.getPosition() >= len) {
        if (effectiveMin > 0) {
            status.setError(
                status.getPosition(),
                "Expected fraction digits not found for: "
                    + this.element.name());
        }
        return;
    }

    if (this.hasDecimalSeparator()) {
        this.decimalSeparator.parse(
            text,
            status,
            attributes,
            null,
            quickPath);

        if (status.isError()) {
            if (effectiveMin == 0) {
                status.clearError();
            }
            return;
        }
    }

    int current = status.getPosition();
    int minEndPos = current + effectiveMin;
    int maxEndPos = Math.min(current + effectiveMax, len);

    if ((minEndPos > len) && leniency.isStrict()) {
        status.setError(
            status.getPosition(),
            "Expected at least " + effectiveMin + " digits.");
        return;
    }

    char zeroChar = (
        quickPath
            ? this.zeroDigit
            : attributes.get(Attributes.ZERO_DIGIT, Character.valueOf('0')).charValue());

    long total = 0;

    while (current < maxEndPos) {
        int digit = text.charAt(current) - zeroChar;

        if ((digit >= 0) && (digit <= 9)) {
            total = total * 10 + digit;
            current++;
        } else if ((current < minEndPos) && leniency.isStrict()) {
            status.setError(
                status.getPosition(),
                "Expected at least " + effectiveMin + " digits.");
            return;
        } else {
            break;
        }
    }

    BigDecimal fraction = new BigDecimal(total);
    fraction = fraction.movePointLeft(current - status.getPosition());

    if (this.element.name().equals("NANO_OF_SECOND")) {
        int num = this.getRealValue(fraction, 0, MRD_MINUS_1);
        parsedResult.put(this.element, num);
    } else {
        // hier nur prototypischer Wert, später fraktionalen Wert bestimmen
        parsedResult.put(FractionalElement.FRACTION, fraction);
        parsedResult.put(this.element, this.element.getDefaultMinimum());
    }

    status.setPosition(current);

}
 
Example 9
Source File: Timestamp.java    From ion-java with Apache License 2.0 4 votes vote down vote up
/**
 * Copies data from a {@link Calendar} into this timestamp.
 * Must only be called during construction due to timestamp immutabliity.
 *
 * @param cal must have at least one field set.
 *
 * @throws IllegalArgumentException if the calendar has no fields set.
 */
private void set_fields_from_calendar(Calendar cal,
                                      Precision precision,
                                      boolean setLocalOffset)
{
    _precision = precision;
    _offset = UNKNOWN_OFFSET;
    boolean dayPrecision = false;
    boolean calendarHasMilliseconds = cal.isSet(Calendar.MILLISECOND);

    switch (this._precision) {
        case FRACTION:
        case SECOND:
            this._second = checkAndCastSecond(cal.get(Calendar.SECOND));
            if (calendarHasMilliseconds) {
                BigDecimal millis = BigDecimal.valueOf(cal.get(Calendar.MILLISECOND));
                this._fraction = millis.movePointLeft(3); // convert to fraction
                checkFraction(precision, this._fraction);
            }
        case MINUTE:
        {
            this._hour   = checkAndCastHour(cal.get(Calendar.HOUR_OF_DAY));
            this._minute = checkAndCastMinute(cal.get(Calendar.MINUTE));

            // If this test is made before calling get(), it will return
            // false even when Calendar.setTimeZone() was called.
            if (setLocalOffset && cal.isSet(Calendar.ZONE_OFFSET))
            {
                int offset = cal.get(Calendar.ZONE_OFFSET);
                if (cal.isSet(Calendar.DST_OFFSET)) {
                    offset += cal.get(Calendar.DST_OFFSET);
                }

                // convert ms to minutes
                _offset = offset / (1000*60);
            }
        }
        case DAY:
            dayPrecision = true;
        case MONTH:
            // Calendar months are 0 based, Timestamp months are 1 based
            this._month  = checkAndCastMonth((cal.get(Calendar.MONTH) + 1));
        case YEAR:
            int year;
            if(cal.get(Calendar.ERA) == GregorianCalendar.AD) {
                year = cal.get(Calendar.YEAR);
            }
            else {
                year = -cal.get(Calendar.YEAR);
            }

            this._year = checkAndCastYear(year);
    }

    if (dayPrecision)
    {
        this._day = checkAndCastDay(cal.get(Calendar.DAY_OF_MONTH), _year, _month);
    }

    if (_offset != UNKNOWN_OFFSET) {
        // Transform our members from local time to Zulu
        this.apply_offset(_offset);
    }
}
 
Example 10
Source File: Timestamp.java    From ion-java with Apache License 2.0 4 votes vote down vote up
private Timestamp(BigDecimal millis, Precision precision, Integer localOffset)
{
    // check bounds to avoid hanging when calling longValue() on decimals with large positive exponents,
    // e.g. 1e10000000
    if(millis.compareTo(MINIMUM_TIMESTAMP_IN_MILLIS_DECIMAL) < 0 ||
            MAXIMUM_ALLOWED_TIMESTAMP_IN_MILLIS_DECIMAL.compareTo(millis) <= 0) {
        throwTimestampOutOfRangeError(millis);
    }
    // quick handle integral zero
    long ms = isIntegralZero(millis) ? 0 : millis.longValue();
    set_fields_from_millis(ms);

    switch (precision)
    {
        case YEAR:
            _month  = 1;
        case MONTH:
            _day    = 1;
        case DAY:
            _hour   = 0;
            _minute = 0;
        case MINUTE:
            _second = 0;
        case SECOND:
        case FRACTION:
    }

    _offset = localOffset;
    // The given BigDecimal may contain greater than milliseconds precision, which is the maximum precision that
    // a Calendar can handle. Set the _fraction here so that extra precision (if any) is not lost.
    // However, don't set the fraction if the given BigDecimal does not have precision at least to the tenth of
    // a second.
    if ((precision.includes(Precision.SECOND)) && millis.scale() > -3) {
        BigDecimal secs = millis.movePointLeft(3);
        BigDecimal secsDown = fastRoundZeroFloor(secs);
        _fraction = secs.subtract(secsDown);
    } else {
        _fraction = null;
    }
    _precision = checkFraction(precision, _fraction);
}
 
Example 11
Source File: OrderedBytes.java    From hbase with Apache License 2.0 4 votes vote down vote up
/**
 * Encode the large magnitude floating point number {@code val} using
 * the key encoding. The caller guarantees that {@code val} will be
 * finite and abs(val) >= 1.0.
 * <p>
 * A floating point value is encoded as an integer exponent {@code E}
 * and a mantissa {@code M}. The original value is equal to
 * {@code (M * 100^E)}. {@code E} is set to the smallest value
 * possible without making {@code M} greater than or equal to 1.0.
 * </p>
 * <p>
 * Each centimal digit of the mantissa is stored in a byte. If the value of
 * the centimal digit is {@code X} (hence {@code X>=0} and
 * {@code X<=99}) then the byte value will be {@code 2*X+1} for
 * every byte of the mantissa, except for the last byte which will be
 * {@code 2*X+0}. The mantissa must be the minimum number of bytes
 * necessary to represent the value; trailing {@code X==0} digits are
 * omitted. This means that the mantissa will never contain a byte with the
 * value {@code 0x00}.
 * </p>
 * <p>
 * If {@code E > 10}, then this routine writes of {@code E} as a
 * varint followed by the mantissa as described above. Otherwise, if
 * {@code E <= 10}, this routine only writes the mantissa and leaves
 * the {@code E} value to be encoded as part of the opening byte of the
 * field by the calling function.
 *
 * <pre>
 *   Encoding:  M       (if E<=10)
 *              E M     (if E>10)
 * </pre>
 * </p>
 * @param dst The destination to which encoded digits are written.
 * @param val The value to encode.
 * @return the number of bytes written.
 */
private static int encodeNumericLarge(PositionedByteRange dst, BigDecimal val) {
  // TODO: this can be done faster
  BigDecimal abs = val.abs();
  byte[] a = dst.getBytes();
  boolean isNeg = val.signum() == -1;
  final int start = dst.getPosition(), offset = dst.getOffset();
  int e = 0, d, startM;

  if (isNeg) { /* Large negative number: 0x08, ~E, ~M */
    dst.put(NEG_LARGE);
  } else { /* Large positive number: 0x22, E, M */
    dst.put(POS_LARGE);
  }

  // normalize abs(val) to determine E
  while (abs.compareTo(E32) >= 0 && e <= 350) { abs = abs.movePointLeft(32); e +=16; }
  while (abs.compareTo(E8) >= 0 && e <= 350) { abs = abs.movePointLeft(8); e+= 4; }
  while (abs.compareTo(BigDecimal.ONE) >= 0 && e <= 350) { abs = abs.movePointLeft(2); e++; }

  // encode appropriate header byte and/or E value.
  if (e > 10) { /* large number, write out {~,}E */
    putVaruint64(dst, e, isNeg);
  } else {
    if (isNeg) { /* Medium negative number: 0x13-E, ~M */
      dst.put(start, (byte) (NEG_MED_MAX - e));
    } else { /* Medium positive number: 0x17+E, M */
      dst.put(start, (byte) (POS_MED_MIN + e));
    }
  }

  // encode M by peeling off centimal digits, encoding x as 2x+1
  startM = dst.getPosition();
  // TODO: 18 is an arbitrary encoding limit. Reevaluate once we have a better handling of
  // numeric scale.
  for (int i = 0; i < 18 && abs.compareTo(BigDecimal.ZERO) != 0; i++) {
    abs = abs.movePointRight(2);
    d = abs.intValue();
    dst.put((byte) (2 * d + 1));
    abs = abs.subtract(BigDecimal.valueOf(d));
  }
  // terminal digit should be 2x
  a[offset + dst.getPosition() - 1] = (byte) (a[offset + dst.getPosition() - 1] & 0xfe);
  if (isNeg) {
    // negative values encoded as ~M
    DESCENDING.apply(a, offset + startM, dst.getPosition() - startM);
  }
  return dst.getPosition() - start;
}
 
Example 12
Source File: BigDecimalMath.java    From big-math with MIT License 3 votes vote down vote up
/**
 * Returns the mantissa of the specified {@link BigDecimal} written as <em>mantissa * 10<sup>exponent</sup></em>.
 *
 * <p>The mantissa is defined as having exactly 1 digit before the decimal point.</p>
 *
 * @param value the {@link BigDecimal}
 * @return the mantissa
 * @see #exponent(BigDecimal)
 */
public static BigDecimal mantissa(BigDecimal value) {
	int exponent = exponent(value);
	if (exponent == 0) {
		return value;
	}

	return value.movePointLeft(exponent);
}
 
Example 13
Source File: Timestamp.java    From ion-java with Apache License 2.0 3 votes vote down vote up
/**
 * Creates a new Timestamp that represents the point in time that is
 * {@code millis} milliseconds (including any fractional
 * milliseconds) from the epoch, with a given local offset.
 *
 * <p>
 * The resulting Timestamp will be precise to the second if {@code millis}
 * doesn't contain information that is more granular than seconds.
 * For example, a {@code BigDecimal} of
 * value <tt>132541995e4 (132541995 &times; 10<sup>4</sup>)</tt>
 * will return a Timestamp of {@code 2012-01-01T12:12:30Z},
 * precise to the second.
 *
 * <p>
 * The resulting Timestamp will be precise to the fractional second if
 * {@code millis} contains information that is at least granular to
 * milliseconds.
 * For example, a {@code BigDecimal} of
 * value <tt>1325419950555</tt>
 * will return a Timestamp of {@code 2012-01-01T12:12:30.555Z},
 * precise to the fractional second.
 *
 * @param millis
 *          number of milliseconds (including any fractional
 *          milliseconds) from the epoch (1970-01-01T00:00:00.000Z);
 *          must not be {@code null}
 * @param localOffset
 *          the local offset from UTC, measured in minutes;
 *          may be {@code null} to represent an unknown local offset
 *
 * @throws NullPointerException if {@code millis} is {@code null}
 *
 * @deprecated Use {@link #forMillis(BigDecimal, Integer)} instead.
 */
@Deprecated
public Timestamp(BigDecimal millis, Integer localOffset)
{
    if (millis == null) throw new NullPointerException("millis is null");

    // check bounds to avoid hanging when calling longValue() on decimals with large positive exponents,
    // e.g. 1e10000000
    if(millis.compareTo(MINIMUM_TIMESTAMP_IN_MILLIS_DECIMAL) < 0 ||
        MAXIMUM_ALLOWED_TIMESTAMP_IN_MILLIS_DECIMAL.compareTo(millis) < 0) {
        throwTimestampOutOfRangeError(millis);
    }

    // quick handle integral zero
    long ms = isIntegralZero(millis) ? 0 : millis.longValue();

    set_fields_from_millis(ms);

    int scale = millis.scale();
    if (scale <= -3) {
        this._precision = Precision.SECOND;
        this._fraction = null;
    }
    else {
        BigDecimal secs = millis.movePointLeft(3);
        BigDecimal secsDown = fastRoundZeroFloor(secs);
        this._fraction = secs.subtract(secsDown);
        this._precision = checkFraction(Precision.SECOND, _fraction);
    }
    this._offset = localOffset;
}
 
Example 14
Source File: CoinUtil.java    From AndroidWallet with GNU General Public License v3.0 2 votes vote down vote up
/**
 * Get the given value in satoshis as a string on the form "10.12345000"
 * using the specified denomination.
 * <p>
 * This method always returns a string with all decimal points. If you only
 * wish to have the necessary digits use
 * {@link CoinUtil#valueString(long, Denomination, boolean)}
 * 
 * @param value
 *           The number of satoshis
 * @param denomination
 *           The denomination to use
 * @return The given value in satoshis as a string on the form "10.12345000".
 */
public static String fullValueString(long value, Denomination denomination) {
   BigDecimal d = BigDecimal.valueOf(value);
   d = d.movePointLeft(denomination.getDecimalPlaces());
   return d.toPlainString();
}
 
Example 15
Source File: CoinUtil.java    From guarda-android-wallets with GNU General Public License v3.0 2 votes vote down vote up
/**
 * Get the given value in satoshis as a string on the form "10.12345000"
 * using the specified denomination.
 * <p>
 * This method always returns a string with all decimal points. If you only
 * wish to have the necessary digits use
 * {@link CoinUtil#valueString(long, Denomination, boolean)}
 * 
 * @param value
 *           The number of satoshis
 * @param denomination
 *           The denomination to use
 * @return The given value in satoshis as a string on the form "10.12345000".
 */
public static String fullValueString(long value, Denomination denomination) {
   BigDecimal d = BigDecimal.valueOf(value);
   d = d.movePointLeft(denomination.getDecimalPlaces());
   return d.toPlainString();
}
 
Example 16
Source File: CoinUtil.java    From bitshares_wallet with MIT License 2 votes vote down vote up
/**
 * Get the given value in satoshis as a string on the form "10.12345000"
 * using the specified denomination.
 * <p>
 * This method always returns a string with all decimal points. If you only
 * wish to have the necessary digits use
 * {@link CoinUtil#valueString(long, Denomination, boolean)}
 * 
 * @param value
 *           The number of satoshis
 * @param denomination
 *           The denomination to use
 * @return The given value in satoshis as a string on the form "10.12345000".
 */
public static String fullValueString(long value, Denomination denomination) {
   BigDecimal d = BigDecimal.valueOf(value);
   d = d.movePointLeft(denomination.getDecimalPlaces());
   return d.toPlainString();
}