java.lang.Object
io.github.tonywasher.joceanus.oceanus.decimal.OceanusDecimal
All Implemented Interfaces:
Comparable<OceanusDecimal>
Direct Known Subclasses:
OceanusMoney, OceanusRate, OceanusRatio, OceanusUnits

public class OceanusDecimal extends Object implements Comparable<OceanusDecimal>
Provides classes to represent decimal numbers with fixed numbers of decimal digits theScale as Long integers. The decimal value is multiplied by 10 to the power of the number of decimals for the number (theFactor). The integral part of the number can be expressed as (Value / Factor) and the fractional part as (Value % Factor). Arithmetic is then performed as whole number arithmetic on these values, with due care taken on multiplication and division to express the result to the correct number of decimals without losing any part of the answer to overflow.
  • Field Details

  • Constructor Details

    • OceanusDecimal

      protected OceanusDecimal()
      Standard constructor.
    • OceanusDecimal

      public OceanusDecimal(String pSource)
      Constructor.
      Parameters:
      pSource - the decimal as a string
      Throws:
      IllegalArgumentException - on invalidly formatted argument
    • OceanusDecimal

      public OceanusDecimal(double pSource)
      Constructor.
      Parameters:
      pSource - the decimal as a double
    • OceanusDecimal

      public OceanusDecimal(OceanusDecimal pSource)
      Constructor.
      Parameters:
      pSource - the source decimal
    • OceanusDecimal

      public OceanusDecimal(long pUnscaledValue, int pScale)
      Constructor.
      Parameters:
      pUnscaledValue - the unscaled value
      pScale - the scale
    • OceanusDecimal

      public OceanusDecimal(byte[] pBuffer)
      Create the decimal from a byte array.
      Parameters:
      pBuffer - the buffer
  • Method Details

    • unscaledValue

      public long unscaledValue()
      Obtain the unscaled value of the decimal.
      Returns:
      the unscaled value
    • scale

      public int scale()
      Obtain the scale of the decimal.
      Returns:
      the scale
    • setValue

      protected final void setValue(long pUnscaledValue, int pScale)
      Set the value and scale.
      Parameters:
      pUnscaledValue - the unscaled value
      pScale - the scale
    • recordScale

      protected final void recordScale(int pScale)
      Record the scale. The unscaled value is unchanged.
      Parameters:
      pScale - the scale
    • adjustToScale

      protected void adjustToScale(int pScale)
      Adjust to scale.
      Parameters:
      pScale - required scale
    • getFactor

      protected static long getFactor(int pDecimals)
      Obtain factor.
      Parameters:
      pDecimals - the number of decimals
      Returns:
      the decimal part of the number
    • isNonZero

      public boolean isNonZero()
      Determine whether we have a non-zero value.
      Returns:
      true if the value is non-zero, false otherwise.
    • isZero

      public boolean isZero()
      Determine whether we have a zero value.
      Returns:
      true if the value is zero, false otherwise.
    • isPositive

      public boolean isPositive()
      Determine whether we have a positive (or zero) value.
      Returns:
      true if the value is non-negative, false otherwise.
    • negate

      public void negate()
      Negate the value.
    • setZero

      public void setZero()
      Set to zero value.
    • signum

      public int signum()
      Returns the sign function.
      Returns:
      -1, 0, or 1 as the value of this Decimal is negative, zero, or positive.
    • reduceScale

      protected final void reduceScale(int pDesiredScale)
      Reduce scale. Remove redundant zero digits in scale.
      Parameters:
      pDesiredScale - the desired scale.
    • adjustDecimals

      protected static long adjustDecimals(long pValue, int iAdjust)
      Adjust a value to a different number of decimals.

      If the adjustment is to reduce the number of decimals, the most significant digit of the discarded digits is examined to determine whether to round up. If the number of decimals is to be increased, zeros are simply added to the end.

      Parameters:
      pValue - the value to adjust
      iAdjust - the adjustment (positive if # of decimals are to increase, negative if they are to decrease)
      Returns:
      the adjusted value
    • calculateProduct

      protected void calculateProduct(OceanusDecimal pFirst, OceanusDecimal pSecond)
      Multiply two decimals together to produce a third.

      This function splits each part of the multiplication into integral and fractional parts (a,b) and (c,d). It then treats each factor as the sum of the two parts (a+b) etc. and calculates the product as (a.c + a.d + b.c + b.d). To avoid losing significant digits at either end of the calculation each partial product is split into integral and fractional parts. The integers are summed together and the fractional parts are summed together at combined decimal places of the two factors. Once all partial products have been calculated, the integral and fractional totals are adjusted to the correct number of decimal places and combined. This allows the multiplication to be built without risk of unnecessary arithmetic overflow.

      Parameters:
      pFirst - the first factor
      pSecond - the second factor
    • calculateQuotient

      protected void calculateQuotient(OceanusDecimal pDividend, OceanusDecimal pDivisor)
      Divide a decimal by another decimal to produce a third.

      The calculation can be written as x.10a/y.10b = (x/y).10a-b = z.10c.

      where x is the unscaled dividend, y the unscaled divisor and z the unscaled result, and a,b,c the relevant scales.

      In order to avoid losing significant digits at either end of the calculation we calculate (x/y) in integer arithmetic.

      x/y = m, x%y = n => x=my + n where m and n are integers, and

      (x/y).10a-b = (my +n).10a-b/y = (m + (n/y)).10a-b

      To obtain the result in the correct scale we find

      z.10c = m.10c-(a-b) + IntegralPart(n.10c-(a-b)/y)

      taking care to round the IntegralPart calculation correctly.

      In the case where it is not possible to avoid overflow, the slower safeQuotient method is used.

      Parameters:
      pDividend - the number to divide
      pDivisor - the number to divide
    • calculateSafeQuotient

      protected void calculateSafeQuotient(OceanusDecimal pDividend, OceanusDecimal pDivisor)
      Divide a decimal by another decimal to produce a third using slow BigDecimal arithmetic.

      This is necessary when the quotient is large since there is a danger of overflow in the standard method

      Parameters:
      pDividend - the number to divide
      pDivisor - the number to divide
    • addValue

      public void addValue(OceanusDecimal pValue)
      Add a Decimal to the value. The value of this Decimal is updated and the scale is maintained.
      Parameters:
      pValue - The Decimal to add to this one.
    • subtractValue

      public void subtractValue(OceanusDecimal pValue)
      Subtract a Decimal from the value. The value of this Decimal is updated and the scale is maintained.
      Parameters:
      pValue - The decimal to subtract from this one.
    • movePointLeft

      public final void movePointLeft(int pPlaces)
      Move decimal point to the left.
      Parameters:
      pPlaces - number of places to move the decimal point
    • movePointRight

      public final void movePointRight(int pPlaces)
      Move decimal point to the right.
      Parameters:
      pPlaces - number of places to move the decimal point
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • max

      public OceanusDecimal max(OceanusDecimal pValue)
      Returns the maximum of this Decimal and pValue.
      Parameters:
      pValue - the value to compare.
      Returns:
      the Decimal whose value is the greater of this Decimal and pValue. If they are equal, as defined by the compareTo method, this is returned
    • min

      public OceanusDecimal min(OceanusDecimal pValue)
      Returns the minimum of this Decimal and pValue.
      Parameters:
      pValue - the value to compare.
      Returns:
      the Decimal whose value is the lesser of this Decimal and pValue. If they are equal, as defined by the compareTo method, this is returned
    • add

      public OceanusDecimal add(OceanusDecimal pValue)
      Returns a new Decimal which is the sum of this Decimal and pValue, and whose scale is the maximum of the two.
      Parameters:
      pValue - the value to add.
      Returns:
      the resulting Decimal
      See Also:
    • subtract

      public OceanusDecimal subtract(OceanusDecimal pValue)
      Returns a new Decimal which is the difference of this Decimal and pValue, and whose scale is the maximum of the two.
      Parameters:
      pValue - the value to subtract.
      Returns:
      the resulting Decimal
      See Also:
    • multiply

      public OceanusDecimal multiply(OceanusDecimal pValue)
      Returns a new Decimal which is the product of this Decimal and pValue, and whose scale is the sum of the two.
      Parameters:
      pValue - the value to multiply by.
      Returns:
      the resulting Decimal
      See Also:
    • multiply

      public void multiply(long pValue)
      Multiplies the value by the amount given. The scale remains the same.
      Parameters:
      pValue - the value to multiply by.
    • divide

      public OceanusDecimal divide(OceanusDecimal pValue)
      Returns a new Decimal whose value is (this / pValue), and whose scale is the same as this Decimal.
      Parameters:
      pValue - the value to divide by.
      Returns:
      the resulting Decimal
      See Also:
    • divide

      public void divide(long pValue)
      Divides the value by the amount given. The scale remains the same.
      Parameters:
      pValue - the value to divide by.
    • divideToIntegralValue

      public OceanusDecimal divideToIntegralValue(OceanusDecimal pValue)
      Returns a new Decimal whose value is the integral part of (this / pValue).
      Parameters:
      pValue - the value to divide by.
      Returns:
      the resulting Decimal
      See Also:
    • remainder

      public OceanusDecimal remainder(OceanusDecimal pValue)
      Returns a new Decimal whose value is (this / pValue), and whose scale is the same as this Decimal.
      Parameters:
      pValue - the value to divide by.
      Returns:
      the resulting Decimal
      See Also:
    • toBigDecimal

      public BigDecimal toBigDecimal()
      Convert the value into a BigDecimal.
      Returns:
      the value as a BigDecimal
    • doubleValue

      public double doubleValue()
      Convert the value into a Double.
      Returns:
      the value as a double
      See Also:
    • floatValue

      public float floatValue()
      Convert the value into a Float.
      Returns:
      the value as a float
      See Also:
    • toBigInteger

      public BigInteger toBigInteger()
      Convert the value into a BigInteger.
      Returns:
      the value as a BigInteger
      See Also:
    • longValue

      public long longValue()
      Convert the value into a long.
      Returns:
      the value as a long
      See Also:
    • intValue

      public int intValue()
      Convert the value into an integer.
      Returns:
      the value as an integer
      See Also:
    • shortValue

      public short shortValue()
      Convert the value into a short.
      Returns:
      the value as a short
      See Also:
    • byteValue

      public byte byteValue()
      Convert the value into a byte.
      Returns:
      the value as a byte
      See Also:
    • checkFractionalZero

      public void checkFractionalZero()
      Check for fractional part on conversion.
    • toBigIntegerExact

      public BigInteger toBigIntegerExact()
      Convert the value into a BigInteger, checking for loss of information.
      Returns:
      the value as a BigInteger
      See Also:
    • longValueExact

      public long longValueExact()
      Convert the value into a long, checking for loss of information.
      Returns:
      the value as a long
      See Also:
    • intValueExact

      public int intValueExact()
      Convert the value into an integer, checking for loss of information.
      Returns:
      the value as an integer
      See Also:
    • shortValueExact

      public short shortValueExact()
      Convert the value into a short, checking for loss of information.
      Returns:
      the value as a short
      See Also:
    • byteValueExact

      public byte byteValueExact()
      Convert the value into a byte, checking for loss of information.
      Returns:
      the value as a byte
      See Also:
    • equals

      public boolean equals(Object pThat)
      Overrides:
      equals in class Object
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class Object
    • compareTo

      public int compareTo(OceanusDecimal pThat)
      Specified by:
      compareTo in interface Comparable<OceanusDecimal>
    • toBytes

      public byte[] toBytes()
      Convert the Decimal to a byte array.
      Returns:
      the byte array