diff --git a/dev-utils/src/main/java/cn/org/codecrafters/devutils/ChainedCalcUtil.java b/dev-utils/src/main/java/cn/org/codecrafters/devutils/ChainedCalcUtil.java new file mode 100644 index 0000000..77c0721 --- /dev/null +++ b/dev-utils/src/main/java/cn/org/codecrafters/devutils/ChainedCalcUtil.java @@ -0,0 +1,352 @@ +/* + * Copyright (C) 2023 CodeCraftersCN. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.org.codecrafters.devutils; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Objects; +import java.util.function.BiFunction; +import java.util.function.Function; + +/** + * Utility class for chained high-precision calculations using BigDecimal. + *
+ * The ChainedCalcUtil class provides a convenient way to perform chained + * high-precision calculations using BigDecimal. It allows users to perform + * mathematical operations such as addition, subtraction, multiplication, + * and division with customizable precision and scale. By using this utility + * class, developers can achieve accurate results and avoid precision loss + * in their calculations. + *
+ * Usage: + *
+ * // Perform addition: 3 + 4 + * BigDecimal result1 = ChainedCalcUtil.startWith(3) + * .add(4) + * .getValue(); + * + * // Perform subtraction: 4 - 2 + * BigDecimal result2 = ChainedCalcUtil.startWith(4) + * .subtract(2) + * .getValue(); + * + * // Perform multiplication: 3 * 6 + * BigDecimal result3 = ChainedCalcUtil.startWith(3) + * .multiply(6) + * .getValue(); + * + * // Perform division: 6 ÷ 2 + * BigDecimal result4 = ChainedCalcUtil.startWith(6) + * .divide(2) + * .getValue(); + * + * // Perform division with specified scale: 13 ÷ 7 with a scale of 2 + * BigDecimal result5 = ChainedCalcUtil.startWith(13) + * .divideWithScale(7, 2) + * .getValue(); + * + * // Get int, long, or double results + * int intResult = ChainedCalcUtil.startWith(3) + * .add(4) + * .getInteger(); + * + * long longResult = ChainedCalcUtil.startWith(4) + * .subtract(2) + * .getLong(); + * + * double doubleResult = ChainedCalcUtil.startWith(6) + * .divide(2) + * .getDouble(); + * + * // Get BigDecimal result with specified scale + * BigDecimal result6 = ChainedCalcUtil.startWith(13) + * .divide(7) + * .getValue(2); + *+ * The above expressions perform various mathematical calculations using the ChainedCalcUtil class. + *
+ * Note:
+ * The ChainedCalcUtil class internally uses BigDecimal to handle high-precision calculations. It is important to note
+ * that BigDecimal operations can be memory-intensive and may have performance implications for extremely large numbers
+ * or complex calculations.
+ *
+ * @author sunzsh
+ * @version 1.0.0
+ * @see java.math.BigDecimal
+ * @since 9 Jul 2023
+ */
+public final class ChainedCalcUtil {
+
+ private BigDecimal value;
+
+ /**
+ * Creates a ChainedCalcUtil instance with the specified initial value.
+ *
+ * @param value the initial value for the calculation
+ */
+ private ChainedCalcUtil(Number value) {
+ this.value = convertBigDecimal(value, null);
+ }
+
+ /**
+ * Starts a chained calculation with the specified initial value.
+ *
+ * @param value the initial value for the calculation
+ * @return a ChainedCalcUtil instance for performing chained calculations
+ */
+ public static ChainedCalcUtil startWith(Number value) {
+ return new ChainedCalcUtil(value);
+ }
+
+ /**
+ * Adds the specified value to the current value.
+ *
+ * @param other the value to be added
+ * @return a ChainedCalcUtil instance with the updated value
+ */
+ public ChainedCalcUtil add(Number other) {
+ return operator(BigDecimal::add, other);
+ }
+
+ /**
+ * Adds the specified value to the current value with a specified scale before the operation.
+ *
+ * @param other the value to be added
+ * @param beforeOperateScale the scale to be applied before the operation
+ * @return a ChainedCalcUtil instance with the updated value
+ */
+ public ChainedCalcUtil add(Number other, Integer beforeOperateScale) {
+ return operator(BigDecimal::add, other, beforeOperateScale);
+ }
+
+ /**
+ * Subtracts the specified value from the current value.
+ *
+ * @param other the value to be subtracted
+ * @return a ChainedCalcUtil instance with the updated value
+ */
+ public ChainedCalcUtil subtract(Number other) {
+ return operator(BigDecimal::subtract, other);
+ }
+
+ /**
+ * Subtracts the specified value from the current value with a specified scale before the operation.
+ *
+ * @param other the value to be subtracted
+ * @param beforeOperateScale the scale to be applied before the operation
+ * @return a ChainedCalcUtil instance with the updated value
+ */
+ public ChainedCalcUtil subtract(Number other, Integer beforeOperateScale) {
+ return operator(BigDecimal::subtract, other, beforeOperateScale);
+ }
+
+ /**
+ * Multiplies the current value by the specified value.
+ *
+ * @param other the value to be multiplied by
+ * @return a ChainedCalcUtil instance with the updated value
+ */
+ public ChainedCalcUtil multiply(Number other) {
+ return operator(BigDecimal::multiply, other);
+ }
+
+ /**
+ * Multiplies the current value by the specified value with a specified scale before the operation.
+ *
+ * @param other the value to be multiplied by
+ * @param beforeOperateScale the scale to be applied before the operation
+ * @return a ChainedCalcUtil instance with the updated value
+ */
+ public ChainedCalcUtil multiply(Number other, Integer beforeOperateScale) {
+ return operator(BigDecimal::multiply, other, beforeOperateScale);
+ }
+
+ /**
+ * Divides the current value by the specified value.
+ *
+ * @param other the value to divide by
+ * @return a ChainedCalcUtil instance with the updated value
+ */
+ public ChainedCalcUtil divide(Number other) {
+ return operator(BigDecimal::divide, other);
+ }
+
+ /**
+ * Divides the current value by the specified value with a specified scale before the operation.
+ *
+ * @param other the value to divide by
+ * @param beforeOperateScale the scale to be applied before the operation
+ * @return a ChainedCalcUtil instance with the updated value
+ */
+ public ChainedCalcUtil divide(Number other, Integer beforeOperateScale) {
+ return operator(BigDecimal::divide, other, beforeOperateScale);
+ }
+
+ /**
+ * Divides the current value by the specified value with a specified scale.
+ *
+ * @param other the value to divide by
+ * @param scale the scale for the result
+ * @return a ChainedCalcUtil instance with the updated value
+ */
+ public ChainedCalcUtil divideWithScale(Number other, Integer scale) {
+ return baseOperator(otherValue ->
+ this.value.divide(otherValue, scale, RoundingMode.HALF_UP), other, null);
+ }
+
+ /**
+ * Divides the current value by the specified value with a specified scale and a scale applied before the operation.
+ *
+ * @param other the value to divide by
+ * @param scale the scale for the result
+ * @param beforeOperateScale the scale to be applied before the operation
+ * @return a ChainedCalcUtil instance with the updated value
+ */
+ public ChainedCalcUtil divideWithScale(Number other, Integer scale, Integer beforeOperateScale) {
+ return baseOperator(otherValue -> this.value.divide(otherValue, scale, RoundingMode.HALF_UP), other, beforeOperateScale);
+ }
+
+ /**
+ * Returns the current value as a BigDecimal.
+ *
+ * @return the current value as a BigDecimal
+ */
+ public BigDecimal getValue() {
+ return value;
+ }
+
+ /**
+ * Returns the current value as a BigDecimal with the specified scale.
+ *
+ * @param scale the scale for the result
+ * @return the current value as a BigDecimal with the specified scale
+ */
+ public BigDecimal getValue(int scale) {
+ return value.setScale(scale, RoundingMode.HALF_UP);
+ }
+
+ /**
+ * Returns the current value as a Double.
+ *
+ * @return the current value as a Double
+ */
+ public Double getDouble() {
+ return getValue().doubleValue();
+ }
+
+ /**
+ * Returns the current value as a Double with the specified scale.
+ *
+ * @param scale the scale for the result
+ * @return the current value as a Double with the specified scale
+ */
+ public Double getDouble(int scale) {
+ return getValue(scale).doubleValue();
+ }
+
+ /**
+ * Returns the current value as a Long.
+ *
+ * @return the current value as a Long
+ */
+ public Long getLong() {
+ return getValue().longValue();
+ }
+
+ /**
+ * Returns the current value as an Integer.
+ *
+ * @return the current value as an Integer
+ */
+ public Integer getInteger() {
+ return getValue().intValue();
+ }
+
+ /**
+ * Applies the specified operator function to the current value and another value.
+ *
+ * @param operator the operator function to apply
+ * @param otherValue the value to apply the operator with
+ * @return a ChainedCalcUtil instance with the updated value
+ */
+ private ChainedCalcUtil operator(BiFunction