1. package com.xxx.common.utils;
    2. import java.math.BigDecimal;
    3. import java.text.NumberFormat;
    4. /**
    5. * 四则运算
    6. *
    7. * @author lt
    8. * @version 2018年11月10日上午9:15:02
    9. */
    10. public class CalcUtil {
    11. /**
    12. * 保留小数位
    13. */
    14. private static final int DEF_DIV_SCALE = 4;
    15. /**
    16. * 结果值
    17. */
    18. private BigDecimal currNum = null;
    19. private CalcUtil(BigDecimal decimal) {
    20. currNum = decimal;
    21. }
    22. /**
    23. * 判断一个数字是否是decimal,不是的话,转换包装
    24. *
    25. * @param v1
    26. * @return
    27. */
    28. private static BigDecimal covertToDecimal(Number v1) {
    29. BigDecimal value;
    30. if (v1 instanceof BigDecimal) {
    31. value = (BigDecimal) v1;
    32. } else {
    33. value = new BigDecimal(v1.toString());
    34. }
    35. return value;
    36. }
    37. /**
    38. * 初始化运算对象
    39. *
    40. * @param v1
    41. * @return
    42. */
    43. public static CalcUtil init(Number v1) {
    44. return new CalcUtil(covertToDecimal(v1));
    45. }
    46. /**
    47. * 直接相加
    48. *
    49. * @return
    50. */
    51. public static CalcUtil addDirect(Number... v2) {
    52. BigDecimal value = BigDecimal.ZERO;
    53. for (Number number : v2) {
    54. value = value.add(covertToDecimal(number));
    55. }
    56. return new CalcUtil(value);
    57. }
    58. /**
    59. * 运算结果后,跟着相加
    60. *
    61. * @param v1
    62. * @return
    63. */
    64. public CalcUtil add(Number... v1) {
    65. for (Number number : v1) {
    66. this.currNum = this.currNum.add(covertToDecimal(number));
    67. }
    68. return this;
    69. }
    70. /**
    71. * 两数直接相减
    72. *
    73. * @param v2 被减数
    74. * @return
    75. */
    76. public static CalcUtil subDirect(Number... v2) {
    77. BigDecimal value = BigDecimal.ZERO;
    78. for (Number number : v2) {
    79. value = value.subtract(covertToDecimal(number));
    80. }
    81. return new CalcUtil(value);
    82. }
    83. /**
    84. * 运算结果后,跟着相减
    85. *
    86. * @param v1 减数
    87. * @return
    88. */
    89. public CalcUtil sub(Number... v1) {
    90. for (Number number : v1) {
    91. this.currNum = this.currNum.subtract(covertToDecimal(number));
    92. }
    93. return this;
    94. }
    95. /**
    96. * 两数直接相乘
    97. *
    98. * @param v2
    99. * @return
    100. */
    101. public static CalcUtil mulDirect(Number... v2) {
    102. BigDecimal value = BigDecimal.ZERO;
    103. for (Number number : v2) {
    104. value = value.multiply(covertToDecimal(number));
    105. }
    106. return new CalcUtil(value);
    107. }
    108. /**
    109. * 运算结果后,跟着相乘
    110. *
    111. * @param v1
    112. * @return
    113. */
    114. public CalcUtil mul(Number... v1) {
    115. for (Number number : v1) {
    116. this.currNum = this.currNum.multiply(covertToDecimal(number));
    117. }
    118. return this;
    119. }
    120. /**
    121. * 两数直接相除
    122. *
    123. * @param v2 被除数
    124. * @return
    125. */
    126. public static CalcUtil divDirect(Number... v2) {
    127. BigDecimal value = BigDecimal.ZERO;
    128. for (Number number : v2) {
    129. // 此处保留20位,减少误差
    130. value = value.divide(covertToDecimal(number), 20, BigDecimal.ROUND_HALF_UP);
    131. }
    132. return new CalcUtil(value);
    133. }
    134. /**
    135. * 运算结果后,跟着相除
    136. *
    137. * @param v1 除数
    138. * @return
    139. */
    140. public CalcUtil div(Number... v1) {
    141. for (Number number : v1) {
    142. // 此处保留20位,减少误差
    143. this.currNum = this.currNum.divide(covertToDecimal(number), 20, BigDecimal.ROUND_HALF_UP);
    144. }
    145. return this;
    146. }
    147. /**
    148. * 返回结果,可不传参数
    149. *
    150. * @param scale 保留位数,默认2位小数
    151. * @return
    152. */
    153. public float floatValue(int... scale) {
    154. if (scale.length > 0) {
    155. return currNum.setScale(scale[0], BigDecimal.ROUND_HALF_UP).floatValue();
    156. }
    157. return currNum.setScale(DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).floatValue();
    158. }
    159. /**
    160. * 返回结果,可不传参数
    161. *
    162. * @param scale 保留位数,默认2位小数
    163. * @return
    164. */
    165. public long longValue(int... scale) {
    166. if (scale.length > 0) {
    167. return currNum.setScale(scale[0], BigDecimal.ROUND_HALF_UP).longValue();
    168. }
    169. return currNum.setScale(DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).longValue();
    170. }
    171. /**
    172. * 返回结果,可不传参数
    173. *
    174. * @param scale 保留位数,默认2位小数
    175. * @return
    176. */
    177. public int intValue(int... scale) {
    178. if (scale.length > 0) {
    179. return currNum.setScale(scale[0], BigDecimal.ROUND_HALF_UP).intValue();
    180. }
    181. return currNum.setScale(DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).intValue();
    182. }
    183. /**
    184. * 返回结果,可不传参数
    185. *
    186. * @param scale 保留位数,默认2位小数
    187. * @return
    188. */
    189. public double doubleValue(int... scale) {
    190. if (scale.length > 0) {
    191. return currNum.setScale(scale[0], BigDecimal.ROUND_HALF_UP).doubleValue();
    192. }
    193. return currNum.setScale(DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
    194. }
    195. /**
    196. * 返回结果,可不传参数
    197. *
    198. * @param scale 保留位数,默认2位小数
    199. * @return
    200. */
    201. public short shortValue(int... scale) {
    202. if (scale.length > 0) {
    203. return currNum.setScale(scale[0], BigDecimal.ROUND_HALF_UP).shortValue();
    204. }
    205. return currNum.setScale(DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).shortValue();
    206. }
    207. /**
    208. * 返回结果,可不传参数
    209. *
    210. * @param scale 保留位数,默认2位小数
    211. * @return
    212. */
    213. public BigDecimal decimalValue(int... scale) {
    214. if (scale.length > 0) {
    215. return currNum.setScale(scale[0], BigDecimal.ROUND_HALF_UP);
    216. }
    217. return currNum.setScale(DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP);
    218. }
    219. /**
    220. * 返回字符串值
    221. *
    222. * @param thousands 是否千分符
    223. * @param scale 保留几位小数
    224. * @return
    225. */
    226. public String stringValue(boolean thousands, int... scale) {
    227. BigDecimal bigDecimal = decimalValue(scale);
    228. NumberFormat numberFormat = NumberFormat.getInstance();
    229. if (scale.length > 0) {
    230. numberFormat.setMinimumFractionDigits(scale[0]);
    231. } else {
    232. numberFormat.setMinimumFractionDigits(DEF_DIV_SCALE);
    233. }
    234. numberFormat.setGroupingUsed(thousands);
    235. return numberFormat.format(bigDecimal);
    236. }
    237. }

    使用方式如下

    1. // 0原生计算
    2. System.out.println("原生:" + (0.1 + 0.2));
    3. // 1.链式操作
    4. double v1 = CalcUtils.init(0).add(0.1).add(0.2).doubleValue();
    5. System.out.println("链式:" + v1);
    6. // 2.直接操作
    7. double v2 = CalcUtils.add(0.1, 0.2).doubleValue();
    8. System.out.println("直接:" + v2);
    9. // 3.混合运算,支持任何类型
    10. float v3 = CalcUtils.add(0.3, 0.5f).mul(0.5d).div(2L).sub(2).add((short) 2).floatValue();
    11. System.out.println("混合运算:" + v3);
    12. // 4.小数位默认2位
    13. double v4 = CalcUtils.div(2, 3).doubleValue();
    14. System.out.println("小数默认2位:" + v4);
    15. // 5.小数位可调整调整
    16. double v5 = CalcUtils.div(2, 3).doubleValue(6);
    17. System.out.println("调整小数位:" + v5);

    结果

    1. 原生: 0.30000000000000004
    2. 链式: 0.3
    3. 直接: 0.3
    4. 混合运算: 0.2
    5. 小数默认2位: 0.67
    6. 调整小数位: 0.666667