From 0e38c09d0421e8cda4a1065dca4a3903bb372838 Mon Sep 17 00:00:00 2001 From: Eugene Kovko <37694937+eukovko@users.noreply.github.com> Date: Mon, 8 Jan 2024 04:07:28 +0100 Subject: [PATCH] BAEL-7448: BigDecimal to Integer (#15569) --- ...BigDecimalToIntegerConversionUnitTest.java | 119 ++++++++++++++++++ ...BigDecimalConversionArgumentsProvider.java | 33 +++++ 2 files changed, 152 insertions(+) create mode 100644 core-java-modules/core-java-numbers-conversions/src/test/java/com/baeldung/bigdecimaltointeger/BigDecimalToIntegerConversionUnitTest.java create mode 100644 core-java-modules/core-java-numbers-conversions/src/test/java/com/baeldung/bigdecimaltointeger/SmallBigDecimalConversionArgumentsProvider.java diff --git a/core-java-modules/core-java-numbers-conversions/src/test/java/com/baeldung/bigdecimaltointeger/BigDecimalToIntegerConversionUnitTest.java b/core-java-modules/core-java-numbers-conversions/src/test/java/com/baeldung/bigdecimaltointeger/BigDecimalToIntegerConversionUnitTest.java new file mode 100644 index 0000000000..a3f89cff92 --- /dev/null +++ b/core-java-modules/core-java-numbers-conversions/src/test/java/com/baeldung/bigdecimaltointeger/BigDecimalToIntegerConversionUnitTest.java @@ -0,0 +1,119 @@ +package com.baeldung.bigdecimaltointeger; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ArgumentsSource; +import org.junit.jupiter.params.provider.ValueSource; + +class BigDecimalToIntegerConversionUnitTest { + + @ParameterizedTest + @ArgumentsSource(SmallBigDecimalConversionArgumentsProvider.class) + void givenSmallBigDecimalWhenConvertToIntegerThenWontLosePrecision(BigDecimal given, int expected) { + int actual = given.intValue(); + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @ValueSource(longs = {Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2, + Long.MAX_VALUE - 3, Long.MAX_VALUE - 4, Long.MAX_VALUE - 5, + Long.MAX_VALUE - 6, Long.MAX_VALUE - 7, Long.MAX_VALUE - 8}) + void givenLargeBigDecimalWhenConvertToIntegerThenLosePrecision(long expected) { + BigDecimal decimal = BigDecimal.valueOf(expected); + int actual = decimal.intValue(); + assertThat(actual) + .isNotEqualTo((int) expected) + .isEqualTo((int) expected - Long.MAX_VALUE - 1); + } + + @ParameterizedTest + @ValueSource(doubles = {0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5}) + void givenLargeBigDecimalWhenConvertToIntegerThenLosePrecision(double given) { + BigDecimal decimal = BigDecimal.valueOf(given); + int integerValue = decimal.intValue(); + double actual = Integer.valueOf(integerValue).doubleValue(); + assertThat(actual) + .isEqualTo((int) given) + .isNotEqualTo(given); + } + + @ParameterizedTest + @ValueSource(doubles = {0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5}) + void givenLargeBigDecimalWhenConvertToIntegerWithRoundingUpThenLosePrecision(double given) { + BigDecimal decimal = BigDecimal.valueOf(given); + int integerValue = decimal.setScale(0, RoundingMode.CEILING).intValue(); + double actual = Integer.valueOf(integerValue).doubleValue(); + assertThat(actual) + .isEqualTo(Math.ceil(given)) + .isNotEqualTo(given); + } + + @ParameterizedTest + @ValueSource(doubles = { + 0.0, 1.00, 2.000, 3.0000, + 4.00000, 5.000000, 6.00000000, + 7.000000000, 8.0000000000}) + void givenLargeBigDecimalWhenCheckScaleThenItGreaterThanZero(double given) { + BigDecimal decimal = BigDecimal.valueOf(given); + assertThat(decimal.scale()).isPositive(); + assertThat(decimal.toBigInteger()).isEqualTo((int) given); + } + + @ParameterizedTest + @ValueSource(doubles = {Long.MAX_VALUE - 0.5, Long.MAX_VALUE - 1.5, Long.MAX_VALUE - 2.5, + Long.MAX_VALUE - 3.5, Long.MAX_VALUE - 4.5, Long.MAX_VALUE - 5.5, + Long.MAX_VALUE - 6.5, Long.MAX_VALUE - 7.5, Long.MAX_VALUE - 8.5}) + void givenLargeBigDecimalWhenConvertToIntegerThenLosePrecisionFromBothSides(double given) { + BigDecimal decimal = BigDecimal.valueOf(given); + int integerValue = decimal.intValue(); + double actual = Integer.valueOf(integerValue).doubleValue(); + assertThat(actual) + .isNotEqualTo(Math.floor(given)) + .isNotEqualTo(given); + } + + @ParameterizedTest + @ValueSource(longs = {Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2, + Long.MAX_VALUE - 3, Long.MAX_VALUE - 4, Long.MAX_VALUE - 5, + Long.MAX_VALUE - 6, Long.MAX_VALUE - 7, Long.MAX_VALUE - 8}) + void givenLargeBigDecimalWhenConvertToExactIntegerThenThrowException(long expected) { + BigDecimal decimal = BigDecimal.valueOf(expected); + assertThatExceptionOfType(ArithmeticException.class) + .isThrownBy(decimal::intValueExact); + } + + @ParameterizedTest + @ValueSource(longs = { + Long.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE - 2, + Long.MIN_VALUE, Long.MIN_VALUE + 1, Long.MIN_VALUE + 2, + 0, 1, 2 + }) + void givenLargeBigDecimalWhenConvertToIntegerThenSetTheMaxOrMinValue(long expected) { + BigDecimal decimal = BigDecimal.valueOf(expected); + boolean tooBig = isTooBig(decimal); + boolean tooSmall = isTooSmall(decimal); + int actual; + if (tooBig) { + actual = Integer.MAX_VALUE; + } else if (tooSmall) { + actual = Integer.MIN_VALUE; + } else { + actual = decimal.intValue(); + } + assertThat(tooBig).isEqualTo(actual == Integer.MAX_VALUE); + assertThat(tooSmall).isEqualTo(actual == Integer.MIN_VALUE); + assertThat(!tooBig && !tooSmall).isEqualTo(actual == expected); + } + + private static boolean isTooSmall(BigDecimal decimal) { + return BigDecimal.valueOf(Integer.MIN_VALUE).compareTo(decimal) > 0; + } + + private static boolean isTooBig(BigDecimal decimal) { + return BigDecimal.valueOf(Integer.MAX_VALUE).compareTo(decimal) < 0; + } +} diff --git a/core-java-modules/core-java-numbers-conversions/src/test/java/com/baeldung/bigdecimaltointeger/SmallBigDecimalConversionArgumentsProvider.java b/core-java-modules/core-java-numbers-conversions/src/test/java/com/baeldung/bigdecimaltointeger/SmallBigDecimalConversionArgumentsProvider.java new file mode 100644 index 0000000000..4588c41fa6 --- /dev/null +++ b/core-java-modules/core-java-numbers-conversions/src/test/java/com/baeldung/bigdecimaltointeger/SmallBigDecimalConversionArgumentsProvider.java @@ -0,0 +1,33 @@ +package com.baeldung.bigdecimaltointeger; + +import java.math.BigDecimal; +import java.util.stream.Stream; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsProvider; + +public class SmallBigDecimalConversionArgumentsProvider implements ArgumentsProvider { + + @Override + public Stream provideArguments(ExtensionContext context) { + return Stream.of( + Arguments.of(BigDecimal.valueOf(0), 0), + Arguments.of(BigDecimal.valueOf(1), 1), + Arguments.of(BigDecimal.valueOf(2), 2), + Arguments.of(BigDecimal.valueOf(3), 3), + Arguments.of(BigDecimal.valueOf(4), 4), + Arguments.of(BigDecimal.valueOf(5), 5), + Arguments.of(BigDecimal.valueOf(6), 6), + Arguments.of(BigDecimal.valueOf(7), 7), + Arguments.of(BigDecimal.valueOf(8), 8), + Arguments.of(BigDecimal.valueOf(9), 9), + Arguments.of(BigDecimal.valueOf(10), 10), + Arguments.of(BigDecimal.valueOf(11), 11), + Arguments.of(BigDecimal.valueOf(12), 12), + Arguments.of(BigDecimal.valueOf(13), 13), + Arguments.of(BigDecimal.valueOf(14), 14), + Arguments.of(BigDecimal.valueOf(15), 15) + ); + } + +}