diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cdcd882..3c675f6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- `Unit.convert()` and `Unit.getConversionMultiplier(Unit)` now strip any trailing fractional zeros and the + scale of the result is >= 0. + ## [7.0.0] - 2025-07-22 ### Added diff --git a/qudtlib-model/src/main/java/io/github/qudtlib/model/Unit.java b/qudtlib-model/src/main/java/io/github/qudtlib/model/Unit.java index 0b04908b..b131e8bc 100644 --- a/qudtlib-model/src/main/java/io/github/qudtlib/model/Unit.java +++ b/qudtlib-model/src/main/java/io/github/qudtlib/model/Unit.java @@ -401,10 +401,16 @@ public BigDecimal convert(BigDecimal value, Unit toUnit, QuantityKind quantityKi ? BigDecimal.ZERO : toUnit.getConversionOffset().orElse(BigDecimal.ZERO); BigDecimal toMultiplier = toUnit.getConversionMultiplier().orElse(BigDecimal.ONE); - return value.add(fromOffset) - .multiply(fromMultiplier, MathContext.DECIMAL128) - .divide(toMultiplier, MathContext.DECIMAL128) - .subtract(toOffset); + BigDecimal result = + value.add(fromOffset) + .multiply(fromMultiplier, MathContext.DECIMAL128) + .divide(toMultiplier, MathContext.DECIMAL128) + .subtract(toOffset) + .stripTrailingZeros(); + if (result.scale() < 0) { + result = result.setScale(0); + } + return result; } /** @@ -427,25 +433,31 @@ public BigDecimal getConversionMultiplier(Unit toUnit) { } Optional fromMultiplier = this.getConversionMultiplier(); Optional toMultiplier = toUnit.getConversionMultiplier(); - return fromMultiplier - .map( - from -> - toMultiplier - .map(to -> from.divide(to, MathContext.DECIMAL128)) - .orElse(null)) - .orElseThrow( - () -> - new InconvertibleQuantitiesException( - String.format( - "Cannot convert %s(%s) to %s(%s)", - this.getIriAbbreviated(), - this.getConversionMultiplier().isEmpty() - ? "no multiplier" - : "has multiplier", - toUnit.getIriAbbreviated(), - toUnit.getConversionMultiplier().isEmpty() - ? "no multiplier" - : "has multiplier"))); + BigDecimal result = + fromMultiplier + .map( + from -> + toMultiplier + .map(to -> from.divide(to, MathContext.DECIMAL128)) + .orElse(null)) + .orElseThrow( + () -> + new InconvertibleQuantitiesException( + String.format( + "Cannot convert %s(%s) to %s(%s)", + this.getIriAbbreviated(), + this.getConversionMultiplier().isEmpty() + ? "no multiplier" + : "has multiplier", + toUnit.getIriAbbreviated(), + toUnit.getConversionMultiplier().isEmpty() + ? "no multiplier" + : "has multiplier"))); + result = result.stripTrailingZeros(); + if (result.scale() < 0) { + result = result.setScale(0); + } + return result; } public boolean conversionOffsetDiffers(Unit other) { diff --git a/qudtlib-test/src/test/java/io/github/qudtlib/QudtTests.java b/qudtlib-test/src/test/java/io/github/qudtlib/QudtTests.java index 1a8ef19d..061b66d1 100644 --- a/qudtlib-test/src/test/java/io/github/qudtlib/QudtTests.java +++ b/qudtlib-test/src/test/java/io/github/qudtlib/QudtTests.java @@ -569,10 +569,12 @@ public void testMilliSV__PER__HR_to_MicroSV__PER__HR() { u.getIriLocalname(), u.getConversionMultiplier().get().toString()))); */ - MatcherAssert.assertThat( + BigDecimal converted = Qudt.convert( - new BigDecimal("15.12"), Units.MilliSV__PER__HR, Units.MicroSV__PER__HR), - Matchers.comparesEqualTo(new BigDecimal(15120))); + new BigDecimal("15.12"), Units.MilliSV__PER__HR, Units.MicroSV__PER__HR); + MatcherAssert.assertThat(converted, Matchers.comparesEqualTo(new BigDecimal(15120))); + BigDecimal expected = new BigDecimal(15120); + assertEquals(expected, converted); } @Test