Skip to content

Commit

Permalink
Merge pull request #299 from glureau/perf_improvements
Browse files Browse the repository at this point in the history
Improve performances of BigDecimal.numberOfDecimalDigits().
  • Loading branch information
ionspin authored Jun 10, 2024
2 parents 4f1d167 + cd3f789 commit aa4202c
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1484,14 +1484,26 @@ class BigDecimal private constructor(
* 12.345 will return 5
* 0.001 will return 4
* 123000 will return 6
* 0.010000 will return 3 (trailing zeros are not counted)
*/
override fun numberOfDecimalDigits(): Long {
val numberOfDigits = when {
exponent in 1L until precision -> precision
exponent > 0 && exponent > precision -> exponent + 1 // Significand is already 10^1 when exponent is > 0
exponent > 0 && exponent == precision -> precision + 1 // Same as above
exponent < 0 -> exponent.absoluteValue + precision
exponent == 0L -> removeTrailingZeroes(this).precision
exponent == 0L -> {
var s = significand
if (s.isZero()) return 1L
var zeroCount = -1L
do {
val res = s.divrem(BigInteger.TEN)
s = res.quotient
zeroCount++
} while (res.remainder.isZero())
precision - zeroCount
}

else -> throw RuntimeException("Invalid case when getting number of decimal digits")
}
return numberOfDigits
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,18 @@ class BigDecimalRoundingTests {

@Test
fun testNumberOfDigits() {
val a = BigDecimal.fromIntWithExponent(123, 3)
val b = BigDecimal.fromIntWithExponent(1, -3)
val c = BigDecimal.fromIntWithExponent(12345, 3)
val d = BigDecimal.fromIntAsSignificand(10000)
assertTrue {
a.numberOfDecimalDigits() == 4L &&
b.numberOfDecimalDigits() == 4L &&
c.numberOfDecimalDigits() == 5L &&
d.numberOfDecimalDigits() == 1L
assertEquals(4, BigDecimal.parseString("1230").numberOfDecimalDigits())
assertEquals(4, BigDecimal.parseString("0.001").numberOfDecimalDigits())
assertEquals(5, BigDecimal.parseString("1234.5").numberOfDecimalDigits())
assertEquals(1, BigDecimal.parseString("1.0000").numberOfDecimalDigits())
assertEquals(5, BigDecimal.parseString("1.0001000").numberOfDecimalDigits())
assertEquals(6, BigDecimal.parseString("10.0001000").numberOfDecimalDigits())
assertEquals(1, BigDecimal.parseString("0").numberOfDecimalDigits())
assertEquals(1, BigDecimal.parseString("0.0").numberOfDecimalDigits())
assertEquals(1, BigDecimal.parseString("00.00").numberOfDecimalDigits())
assertEquals(1, BigDecimal.parseString("1").numberOfDecimalDigits())
assertEquals(2, BigDecimal.parseString("10").numberOfDecimalDigits())
}
}

@Test
fun testRoundSignificand() {
Expand Down

0 comments on commit aa4202c

Please sign in to comment.