我们都知道浮点型变量在进行计算的时候会出现丢失精度的问题。

    Java中float的精度为6-7位有效数字。double的精度为15-16位。

    1. add(BigDecimal) BigDecimal对象中的值相加,然后返回这个对象。
    2. subtract(BigDecimal) BigDecimal对象中的值相减,然后返回这个对象。
    3. multiply(BigDecimal) BigDecimal对象中的值相乘,然后返回这个对象。
    4. divide(BigDecimal) BigDecimal对象中的值相除,然后返回这个对象。
    5. toString() BigDecimal对象的数值转换成字符串。
    6. doubleValue() BigDecimal对象中的值以双精度数返回。
    7. floatValue() BigDecimal对象中的值以单精度数返回。
    8. longValue() BigDecimal对象中的值以长整数返回。
    9. intValue() BigDecimal对象中的值以整数返回。

    一般使用BigDecimal来解决商业运算上丢失精度的问题的时候,声明BigDecimal对象的时候一定要使用它构造参数为String的类型的构造器。

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