1. /**
    2. * 用于高精确处理常用的数学运算
    3. */
    4. public class ArithmeticUtils {
    5. //默认除法运算精度
    6. private static final int DEF_DIV_SCALE = 10;
    7. /**
    8. * 提供精确的加法运算
    9. *
    10. * @param v1 被加数
    11. * @param v2 加数
    12. * @return 两个参数的和
    13. */
    14. public static double add(double v1, double v2) {
    15. BigDecimal b1 = new BigDecimal(Double.toString(v1));
    16. BigDecimal b2 = new BigDecimal(Double.toString(v2));
    17. return b1.add(b2).doubleValue();
    18. }
    19. /**
    20. * 提供精确的加法运算
    21. *
    22. * @param v1 被加数
    23. * @param v2 加数
    24. * @return 两个参数的和
    25. */
    26. public static BigDecimal add(String v1, String v2) {
    27. BigDecimal b1 = new BigDecimal(v1);
    28. BigDecimal b2 = new BigDecimal(v2);
    29. return b1.add(b2);
    30. }
    31. /**
    32. * 提供精确的加法运算
    33. *
    34. * @param v1 被加数
    35. * @param v2 加数
    36. * @param scale 保留scale 位小数
    37. * @return 两个参数的和
    38. */
    39. public static String add(String v1, String v2, int scale) {
    40. if (scale < 0) {
    41. throw new IllegalArgumentException(
    42. "The scale must be a positive integer or zero");
    43. }
    44. BigDecimal b1 = new BigDecimal(v1);
    45. BigDecimal b2 = new BigDecimal(v2);
    46. return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
    47. }
    48. /**
    49. * 提供精确的减法运算
    50. *
    51. * @param v1 被减数
    52. * @param v2 减数
    53. * @return 两个参数的差
    54. */
    55. public static double sub(double v1, double v2) {
    56. BigDecimal b1 = new BigDecimal(Double.toString(v1));
    57. BigDecimal b2 = new BigDecimal(Double.toString(v2));
    58. return b1.subtract(b2).doubleValue();
    59. }
    60. /**
    61. * 提供精确的减法运算。
    62. *
    63. * @param v1 被减数
    64. * @param v2 减数
    65. * @return 两个参数的差
    66. */
    67. public static BigDecimal sub(String v1, String v2) {
    68. BigDecimal b1 = new BigDecimal(v1);
    69. BigDecimal b2 = new BigDecimal(v2);
    70. return b1.subtract(b2);
    71. }
    72. /**
    73. * 提供精确的减法运算
    74. *
    75. * @param v1 被减数
    76. * @param v2 减数
    77. * @param scale 保留scale 位小数
    78. * @return 两个参数的差
    79. */
    80. public static String sub(String v1, String v2, int scale) {
    81. if (scale < 0) {
    82. throw new IllegalArgumentException(
    83. "The scale must be a positive integer or zero");
    84. }
    85. BigDecimal b1 = new BigDecimal(v1);
    86. BigDecimal b2 = new BigDecimal(v2);
    87. return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
    88. }
    89. /**
    90. * 提供精确的乘法运算
    91. *
    92. * @param v1 被乘数
    93. * @param v2 乘数
    94. * @return 两个参数的积
    95. */
    96. public static double mul(double v1, double v2) {
    97. BigDecimal b1 = new BigDecimal(Double.toString(v1));
    98. BigDecimal b2 = new BigDecimal(Double.toString(v2));
    99. return b1.multiply(b2).doubleValue();
    100. }
    101. /**
    102. * 提供精确的乘法运算
    103. *
    104. * @param v1 被乘数
    105. * @param v2 乘数
    106. * @return 两个参数的积
    107. */
    108. public static BigDecimal mul(String v1, String v2) {
    109. BigDecimal b1 = new BigDecimal(v1);
    110. BigDecimal b2 = new BigDecimal(v2);
    111. return b1.multiply(b2);
    112. }
    113. /**
    114. * 提供精确的乘法运算
    115. *
    116. * @param v1 被乘数
    117. * @param v2 乘数
    118. * @param scale 保留scale 位小数
    119. * @return 两个参数的积
    120. */
    121. public static double mul(double v1, double v2, int scale) {
    122. BigDecimal b1 = new BigDecimal(Double.toString(v1));
    123. BigDecimal b2 = new BigDecimal(Double.toString(v2));
    124. return round(b1.multiply(b2).doubleValue(), scale);
    125. }
    126. /**
    127. * 提供精确的乘法运算
    128. *
    129. * @param v1 被乘数
    130. * @param v2 乘数
    131. * @param scale 保留scale 位小数
    132. * @return 两个参数的积
    133. */
    134. public static String mul(String v1, String v2, int scale) {
    135. if (scale < 0) {
    136. throw new IllegalArgumentException(
    137. "The scale must be a positive integer or zero");
    138. }
    139. BigDecimal b1 = new BigDecimal(v1);
    140. BigDecimal b2 = new BigDecimal(v2);
    141. return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
    142. }
    143. /**
    144. * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
    145. * 小数点以后10位,以后的数字四舍五入
    146. *
    147. * @param v1 被除数
    148. * @param v2 除数
    149. * @return 两个参数的商
    150. */
    151. public static double div(double v1, double v2) {
    152. return div(v1, v2, DEF_DIV_SCALE);
    153. }
    154. /**
    155. * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
    156. * 定精度,以后的数字四舍五入
    157. *
    158. * @param v1 被除数
    159. * @param v2 除数
    160. * @param scale 表示表示需要精确到小数点以后几位。
    161. * @return 两个参数的商
    162. */
    163. public static double div(double v1, double v2, int scale) {
    164. if (scale < 0) {
    165. throw new IllegalArgumentException("The scale must be a positive integer or zero");
    166. }
    167. BigDecimal b1 = new BigDecimal(Double.toString(v1));
    168. BigDecimal b2 = new BigDecimal(Double.toString(v2));
    169. return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    170. }
    171. /**
    172. * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
    173. * 定精度,以后的数字四舍五入
    174. *
    175. * @param v1 被除数
    176. * @param v2 除数
    177. * @param scale 表示需要精确到小数点以后几位
    178. * @return 两个参数的商
    179. */
    180. public static String div(String v1, String v2, int scale) {
    181. if (scale < 0) {
    182. throw new IllegalArgumentException("The scale must be a positive integer or zero");
    183. }
    184. BigDecimal b1 = new BigDecimal(v1);
    185. BigDecimal b2 = new BigDecimal(v1);
    186. return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();
    187. }
    188. /**
    189. * 提供精确的小数位四舍五入处理
    190. *
    191. * @param v 需要四舍五入的数字
    192. * @param scale 小数点后保留几位
    193. * @return 四舍五入后的结果
    194. */
    195. public static double round(double v, int scale) {
    196. if (scale < 0) {
    197. throw new IllegalArgumentException("The scale must be a positive integer or zero");
    198. }
    199. BigDecimal b = new BigDecimal(Double.toString(v));
    200. return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    201. }
    202. /**
    203. * 提供精确的小数位四舍五入处理
    204. *
    205. * @param v 需要四舍五入的数字
    206. * @param scale 小数点后保留几位
    207. * @return 四舍五入后的结果
    208. */
    209. public static String round(String v, int scale) {
    210. if (scale < 0) {
    211. throw new IllegalArgumentException(
    212. "The scale must be a positive integer or zero");
    213. }
    214. BigDecimal b = new BigDecimal(v);
    215. return b.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
    216. }
    217. /**
    218. * 取余数
    219. *
    220. * @param v1 被除数
    221. * @param v2 除数
    222. * @param scale 小数点后保留几位
    223. * @return 余数
    224. */
    225. public static String remainder(String v1, String v2, int scale) {
    226. if (scale < 0) {
    227. throw new IllegalArgumentException(
    228. "The scale must be a positive integer or zero");
    229. }
    230. BigDecimal b1 = new BigDecimal(v1);
    231. BigDecimal b2 = new BigDecimal(v2);
    232. return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
    233. }
    234. /**
    235. * 取余数 BigDecimal
    236. *
    237. * @param v1 被除数
    238. * @param v2 除数
    239. * @param scale 小数点后保留几位
    240. * @return 余数
    241. */
    242. public static BigDecimal remainder(BigDecimal v1, BigDecimal v2, int scale) {
    243. if (scale < 0) {
    244. throw new IllegalArgumentException(
    245. "The scale must be a positive integer or zero");
    246. }
    247. return v1.remainder(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);
    248. }
    249. /**
    250. * 比较大小
    251. *
    252. * @param v1 被比较数
    253. * @param v2 比较数
    254. * @return 如果v1 大于v2 则 返回true 否则false
    255. */
    256. public static boolean compare(String v1, String v2) {
    257. BigDecimal b1 = new BigDecimal(v1);
    258. BigDecimal b2 = new BigDecimal(v2);
    259. int bj = b1.compareTo(b2);
    260. boolean res;
    261. if (bj > 0)
    262. res = true;
    263. else
    264. res = false;
    265. return res;
    266. }
    267. }

    工具类2

    1. import java.math.BigDecimal;
    2. import java.math.RoundingMode;
    3. import java.text.NumberFormat;
    4. /**
    5. * @Description:全局 BigDecimal 工具类
    6. * @Author: tarzan
    7. * @Date: 2021/09/31 9:06
    8. */
    9. public class SmartBigDecimalUtil {
    10. /**
    11. * 价格类型 保留小数点 2
    12. */
    13. public static final int PRICE_DECIMAL_POINT = 2;
    14. /**
    15. * 价格类型 保留小数点 6
    16. */
    17. public static final int SIX_PRICE_DECIMAL_POINT = 6;
    18. /**
    19. * 重量类型保留小数点 3
    20. */
    21. public static final int WEIGHT_DECIMAL_POINT = 3;
    22. /**
    23. * 金额相关计算方法:四舍五入 保留2位小数点
    24. */
    25. public static class Amount {
    26. public static BigDecimal add(BigDecimal num1, BigDecimal num2) {
    27. return setScale(num1.add(num2), PRICE_DECIMAL_POINT);
    28. }
    29. public static BigDecimal multiply(BigDecimal num1, BigDecimal num2) {
    30. return setScale(num1.multiply(num2), PRICE_DECIMAL_POINT);
    31. }
    32. public static BigDecimal subtract(BigDecimal num1, BigDecimal num2) {
    33. return setScale(num1.subtract(num2), PRICE_DECIMAL_POINT);
    34. }
    35. public static BigDecimal divide(BigDecimal num1, BigDecimal num2) {
    36. return setScale(num1.divide(num2, RoundingMode.HALF_UP), PRICE_DECIMAL_POINT);
    37. }
    38. }
    39. /**
    40. * 金额相关计算方法:四舍五入 保留2位小数点
    41. */
    42. public static class AmountSix {
    43. public static BigDecimal add(BigDecimal num1, BigDecimal num2) {
    44. return setScale(num1.add(num2), SIX_PRICE_DECIMAL_POINT);
    45. }
    46. public static BigDecimal multiply(BigDecimal num1, BigDecimal num2) {
    47. return setScale(num1.multiply(num2), SIX_PRICE_DECIMAL_POINT);
    48. }
    49. public static BigDecimal subtract(BigDecimal num1, BigDecimal num2) {
    50. return setScale(num1.subtract(num2), SIX_PRICE_DECIMAL_POINT);
    51. }
    52. public static BigDecimal divide(BigDecimal num1, BigDecimal num2) {
    53. return num1.divide(num2, PRICE_DECIMAL_POINT, RoundingMode.HALF_UP);
    54. }
    55. }
    56. /**
    57. * 重量相关计算方法:四舍五入 保留3位小数点
    58. */
    59. public static class Weight {
    60. public static BigDecimal add(BigDecimal num1, BigDecimal num2) {
    61. return setScale(num1.add(num2), WEIGHT_DECIMAL_POINT);
    62. }
    63. public static BigDecimal multiply(BigDecimal num1, BigDecimal num2) {
    64. return setScale(num1.multiply(num2), WEIGHT_DECIMAL_POINT);
    65. }
    66. public static BigDecimal subtract(BigDecimal num1, BigDecimal num2) {
    67. return setScale(num1.subtract(num2), WEIGHT_DECIMAL_POINT);
    68. }
    69. public static BigDecimal divide(BigDecimal num1, BigDecimal num2) {
    70. return num1.divide(num2, WEIGHT_DECIMAL_POINT, RoundingMode.HALF_UP);
    71. }
    72. }
    73. /**
    74. * BigDecimal 加法 num1 + num2
    75. * 未做非空校验
    76. *
    77. * @param num1
    78. * @param num2
    79. * @param point 请使用BigDecimalUtils.PRICE_DECIMAL_POINT | BigDecimalUtils.WEIGHT_DECIMAL_POINT
    80. * @return BigDecimal
    81. */
    82. public static BigDecimal add(BigDecimal num1, BigDecimal num2, int point) {
    83. return setScale(num1.add(num2), point);
    84. }
    85. /**
    86. * BigDecimal 乘法 num1 x num2
    87. * 未做非空校验
    88. *
    89. * @param num1
    90. * @param num2
    91. * @param point 请使用BigDecimalUtils.PRICE_DECIMAL_POINT | BigDecimalUtils.WEIGHT_DECIMAL_POINT
    92. * @return BigDecimal
    93. */
    94. public static BigDecimal multiply(BigDecimal num1, BigDecimal num2, int point) {
    95. return setScale(num1.multiply(num2), point);
    96. }
    97. /**
    98. * BigDecimal 减法 num1 - num2
    99. * 未做非空校验
    100. *
    101. * @param num1
    102. * @param num2
    103. * @param point 请使用BigDecimalUtils.PRICE_DECIMAL_POINT | BigDecimalUtils.WEIGHT_DECIMAL_POINT
    104. * @return BigDecimal
    105. */
    106. public static BigDecimal subtract(BigDecimal num1, BigDecimal num2, int point) {
    107. return setScale(num1.subtract(num2), point);
    108. }
    109. /**
    110. * BigDecimal 除法 num1/num2
    111. * 未做非空校验
    112. *
    113. * @param num1
    114. * @param num2
    115. * @param point 请使用BigDecimalUtils.PRICE_DECIMAL_POINT | BigDecimalUtils.WEIGHT_DECIMAL_POINT
    116. * @return BigDecimal
    117. */
    118. public static BigDecimal divide(BigDecimal num1, BigDecimal num2, int point) {
    119. return num1.divide(num2, point, RoundingMode.HALF_UP);
    120. }
    121. /**
    122. * 设置小数点类型为 四舍五入
    123. *
    124. * @param num
    125. * @param point
    126. * @return BigDecimal
    127. */
    128. public static BigDecimal setScale(BigDecimal num, int point) {
    129. return num.setScale(point, RoundingMode.HALF_UP);
    130. }
    131. /**
    132. * 比较 num1 是否大于 num2
    133. *
    134. * @param num1
    135. * @param num2
    136. * @return boolean
    137. */
    138. public static boolean isGreaterThan(BigDecimal num1, BigDecimal num2) {
    139. return num1.compareTo(num2) == 1;
    140. }
    141. /**
    142. * 比较 num1 是否大于等于 num2
    143. *
    144. * @param num1
    145. * @param num2
    146. * @return boolean
    147. */
    148. public static boolean isGreaterOrEqual(BigDecimal num1, BigDecimal num2) {
    149. return isGreaterThan(num1, num2) || equals(num1, num2);
    150. }
    151. /**
    152. * 比较 num1 是否小于 num2
    153. *
    154. * @param num1
    155. * @param num2
    156. * @return boolean
    157. */
    158. public static boolean isLessThan(BigDecimal num1, BigDecimal num2) {
    159. return num1.compareTo(num2) == - 1;
    160. }
    161. /**
    162. * 比较 num1 是否小于等于 num2
    163. *
    164. * @param num1
    165. * @param num2
    166. * @return boolean
    167. */
    168. public static boolean isLessOrEqual(BigDecimal num1, BigDecimal num2) {
    169. return isLessThan(num1, num2) || equals(num1, num2);
    170. }
    171. /**
    172. * 比较 num1 是否等于 num2
    173. *
    174. * @param num1
    175. * @param num2
    176. * @return
    177. */
    178. public static boolean equals(BigDecimal num1, BigDecimal num2) {
    179. return num1.compareTo(num2) == 0;
    180. }
    181. /**
    182. * 计算 num1 / num2 的百分比
    183. *
    184. * @param num1
    185. * @param num2
    186. * @return String
    187. */
    188. public static String getPercentage(BigDecimal num1, BigDecimal num2) {
    189. BigDecimal result = num1.divide(num2, 4, RoundingMode.HALF_UP);
    190. NumberFormat percent = NumberFormat.getPercentInstance();
    191. percent.setMaximumFractionDigits(2);
    192. return percent.format(result.doubleValue());
    193. }
    194. /**
    195. * 计算 num1 / num2 的百分比
    196. *
    197. * @param num1
    198. * @param num2
    199. * @param point 保留几位小数
    200. * @return String
    201. */
    202. public static BigDecimal bigDecimalPercent(Integer num1, Integer num2, int point) {
    203. if (num1 == null || num2 == null) {
    204. return BigDecimal.ZERO;
    205. }
    206. if (num2.equals(Integer.valueOf(0))) {
    207. return BigDecimal.ZERO;
    208. }
    209. BigDecimal bigDecimalNum1 = new BigDecimal(num1);
    210. BigDecimal bigDecimalNum2 = new BigDecimal(num2);
    211. return bigDecimalPercent(bigDecimalNum1, bigDecimalNum2, point);
    212. }
    213. /**
    214. * 计算 num1 / num2 的百分比
    215. *
    216. * @param num1
    217. * @param num2
    218. * @param point 保留几位小数
    219. * @return String
    220. */
    221. public static BigDecimal bigDecimalPercent(BigDecimal num1, BigDecimal num2, int point) {
    222. if (num1 == null || num2 == null) {
    223. return BigDecimal.ZERO;
    224. }
    225. if (equals(BigDecimal.ZERO, num2)) {
    226. return BigDecimal.ZERO;
    227. }
    228. BigDecimal percent = num1.divide(num2, point + 2, RoundingMode.HALF_UP);
    229. BigDecimal percent100 = percent.multiply(new BigDecimal(100)).setScale(point);
    230. return percent100;
    231. }
    232. /**
    233. * 判断num是否为空 或者 零
    234. *
    235. * @param num
    236. * @return String
    237. */
    238. public static Boolean isEmpty(BigDecimal num) {
    239. return null == num || equals(BigDecimal.ZERO, num);
    240. }
    241. /**
    242. * 判断num是否 不等于null 并且不等于零
    243. *
    244. * @param num
    245. * @return String
    246. */
    247. public static Boolean isNotEmpty(BigDecimal num) {
    248. return ! isEmpty(num);
    249. }
    250. /**
    251. * 转换为万
    252. *
    253. * @param num
    254. * @param point
    255. * @return
    256. */
    257. public static BigDecimal convertTenThousand(BigDecimal num, int point) {
    258. BigDecimal decimal = num.divide(new BigDecimal(10000), point, RoundingMode.HALF_UP);
    259. return decimal;
    260. }
    261. /**
    262. * 转换为负数
    263. *
    264. * @param num
    265. * @return
    266. */
    267. public static BigDecimal convertToMinusNumber(BigDecimal num) {
    268. if (isLessOrEqual(num, BigDecimal.ZERO)) {
    269. return num;
    270. }
    271. return BigDecimal.ZERO.subtract(num);
    272. }
    273. }

    工具类3

    1. /**
    2. * @author wuke
    3. * @date 2022年03月22日 11:37
    4. */
    5. public class BigDecimalUtil {
    6. /**
    7. * 对BigDecimal求2次平方根,精度无损失。
    8. */
    9. public static BigDecimal sqrt(BigDecimal value) {
    10. BigDecimal val = BigDecimal.valueOf(Math.sqrt(value.doubleValue()));
    11. return val.add(BigDecimal.valueOf(value.subtract(val.multiply(val)).doubleValue() / (val.doubleValue() * 2.0)));
    12. }
    13. /**
    14. * 对BigDecimal求平方根,结果四舍五入
    15. *
    16. * @param scale 几次方
    17. * @return java.math.BigDecimal
    18. * @author wuke
    19. * @date 2022/3/22 14:06
    20. */
    21. public static BigDecimal sqrt(BigDecimal value, int scale) {
    22. if (value.compareTo(BigDecimal.ZERO) == 0) {
    23. return new BigDecimal(0);
    24. }
    25. BigDecimal num2 = BigDecimal.valueOf(2);
    26. int precision = 100;
    27. BigDecimal deviation = value;
    28. int cnt = 0;
    29. while (cnt < precision) {
    30. deviation = (deviation.add(value.divide(deviation, 100, RoundingMode.HALF_UP))).divide(num2, 100, RoundingMode.HALF_UP);
    31. cnt++;
    32. }
    33. deviation = deviation.setScale(scale, RoundingMode.HALF_UP);
    34. return deviation;
    35. }
    36. }