-
Notifications
You must be signed in to change notification settings - Fork 46
BigDecimal Usage Overview
To create a BigDecimal you can parse a string in expanded or scientific notation
Scientific
val bigDecimal = BigDecimal.parseString("1.23E-6)")
println("BigDecimal: $bigDecimal")
----- Output -----
BigDecimal: 1.23E-6Expanded
val bigDecimal = BigDecimal.parseString("0.00000123")
println("BigDecimal: $bigDecimal")
----- Output -----
BigDecimal: 1.23E-6You can convert standard types to BigDecimal, i.e. Long
val bigDecimal = BigDecimal.fromLong(7111)
println("BigDecimal: $bigDecimal")
----- Output -----
BigDecimal: 7.111E+3Or you can specify an exponent. when you do specify an exponent, input value (long, int, short, byte) is considered to be in scientific notation.
val bigDecimal = BigDecimal.fromLongWithExponent(1, (-5).toBigInteger())
println("BigDecimal: $bigDecimal")
println("BigDecimalExpanded: ${bigDecimal.toStringExpanded()}")
----- Output -----
BigDecimal: 1.0E-5
BigDecimalExpanded: 0.00001
For String
val bigDecimal = "12345678.123".toBigIntegerOr for Double of Float
val bigDecimalFromFloat = 123.456f.toBigDecimal()
val bigDecimalFromDouble = 123.456.toBigDecimal()
By default toString() is returned in scientific output, but expanded output is also available
val bigDecimal = BigDecimal.parseString("123.456")
println("BigDecimal: ${bigDecimal.toStringExpanded()}")
bigDecimal.toStringExpanded() == "123.456"
----- Output -----
BigDecimal: 123.456Standard arithmetic operations that are present:
- Addition
- Subtraction
- Multiplication
- Division
- Exponentiation
- Increase by one
- Decrease by one
- Absolute value
- Negate
- Signum
(Suspiciously missing is square root, both from BigInteger and BigDecimal, should be added soon™)
Operations are executed with existing significands and then rounded down afterwards. Decimal mode parameter controls the precision and rounding mode
This is a counterpart to the Java BigDecimal MathContext.
data class DecimalMode(val decimalPrecision : Long = 0, val roundingMode : RoundingMode = RoundingMode.NONE)decimalPrecision defines how many digits should significand have
roundingMode defines rounding mode.
-
DecimalModesupplied to the operation always overrides all otherDecimalModesset inBigDecimals -
If a
DecimalModeis set when creating aBigDecimalthat mode will be used for all operations. -
If two
BigDecimals have differentDecimalModeswith different RoundingModes anArithmeticExceptionwill be thrown. If the modes are same, but the precision is different, larger precision will be used.
Precision 0 and roundingMode none attempt to provide infinite precisions. Exception is division, where default precision is
is the sum of precisions of operands (or 6, if the sum is below 6). If result of the operation cannot fit inside precision and RoundingMode is NONE, ArithmeticException
will be thrown.
Example from the tests:
fun readmeDivisionTest() {
assertFailsWith(ArithmeticException::class) {
val a = 1.toBigDecimal()
val b = 3.toBigDecimal()
val result = a/b
}
assertTrue {
val a = 1.toBigDecimal()
val b = 3.toBigDecimal()
val result = a.div(b, DecimalMode(20, RoundingMode.ROUND_HALF_AWAY_FROM_ZERO))
result.toString() == "3.3333333333333333333E-1"
}
}| Name | Description |
|---|---|
| FLOOR | Towards negative infinity |
| CEILING | Towards positive infinity |
| AWAY_FROM_ZERO | Away from zero |
| TOWARDS_ZERO | Towards zero |
| NONE | Infinite decimalPrecision, and beyond |
| ROUND_HALF_AWAY_FROM_ZERO | Round towards nearest integer, using towards zero as tie breaker when significant digit being rounded is 5 |
| ROUND_HALF_TOWARDS_ZERO | Round towards nearest integer, using away from zero as tie breaker when significant digit being rounded is 5 |
| ROUND_HALF_CEILING | Round towards nearest integer, using towards infinity as tie breaker when significant digit being rounded is 5 |
| ROUND_HALF_FLOOR | Round towards nearest integer, using towards negative infinity as tie breaker when significant digit being rounded is 5 |