个人随笔
目录
工具类:Java浮点数四则运算
2020-09-11 23:00:43

有时候,我们对double进行加减乘除会导致精度丢失,具体原因可参考: java中float和double精度问题以及解决方案,这里提供了一个工具类可以完美的进行计算:

  1. import java.math.BigDecimal;
  2. /**
  3. * 进行BigDecimal对象的加减乘除,四舍五入等运算的工具类
  4. * @author ameyume
  5. *
  6. */
  7. public class Arith {
  8. /**
  9. * 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精
  10. * 确的浮点数运算,包括加减乘除和四舍五入。
  11. */
  12. //默认除法运算精度
  13. private static final int DEF_DIV_SCALE = 10;
  14. //这个类不能实例化
  15. private Arith(){
  16. }
  17. /**
  18. * 提供精确的加法运算。
  19. * @param v1 被加数
  20. * @param v2 加数
  21. * @return 两个参数的和
  22. */
  23. public static double add(double v1,double v2){
  24. BigDecimal b1 = new BigDecimal(Double.toString(v1));
  25. BigDecimal b2 = new BigDecimal(Double.toString(v2));
  26. return b1.add(b2).doubleValue();
  27. }
  28. /**
  29. * 提供精确的减法运算。
  30. * @param v1 被减数
  31. * @param v2 减数
  32. * @return 两个参数的差
  33. */
  34. public static double sub(double v1,double v2){
  35. BigDecimal b1 = new BigDecimal(Double.toString(v1));
  36. BigDecimal b2 = new BigDecimal(Double.toString(v2));
  37. return b1.subtract(b2).doubleValue();
  38. }
  39. /**
  40. * 提供精确的乘法运算。
  41. * @param v1 被乘数
  42. * @param v2 乘数
  43. * @return 两个参数的积
  44. */
  45. public static double mul(double v1,double v2){
  46. BigDecimal b1 = new BigDecimal(Double.toString(v1));
  47. BigDecimal b2 = new BigDecimal(Double.toString(v2));
  48. return b1.multiply(b2).doubleValue();
  49. }
  50. /**
  51. * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
  52. * 小数点以后10位,以后的数字四舍五入。
  53. * @param v1 被除数
  54. * @param v2 除数
  55. * @return 两个参数的商
  56. */
  57. public static double div(double v1,double v2){
  58. return div(v1,v2,DEF_DIV_SCALE);
  59. }
  60. /**
  61. * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
  62. * 定精度,以后的数字四舍五入。
  63. * @param v1 被除数
  64. * @param v2 除数
  65. * @param scale 表示表示需要精确到小数点以后几位。
  66. * @return 两个参数的商
  67. */
  68. public static double div(double v1,double v2,int scale){
  69. if(scale<0){
  70. throw new IllegalArgumentException(
  71. "The scale must be a positive integer or zero");
  72. }
  73. BigDecimal b1 = new BigDecimal(Double.toString(v1));
  74. BigDecimal b2 = new BigDecimal(Double.toString(v2));
  75. return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
  76. }
  77. /**
  78. * 提供精确的小数位四舍五入处理。
  79. * @param v 需要四舍五入的数字
  80. * @param scale 小数点后保留几位
  81. * @return 四舍五入后的结果
  82. */
  83. public static double round(double v,int scale){
  84. if(scale<0){
  85. throw new IllegalArgumentException(
  86. "The scale must be a positive integer or zero");
  87. }
  88. BigDecimal b = new BigDecimal(Double.toString(v));
  89. BigDecimal one = new BigDecimal("1");
  90. return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
  91. }
  92. /**
  93. * 提供精确的类型转换(Float)
  94. * @param v 需要被转换的数字
  95. * @return 返回转换结果
  96. */
  97. public static float convertsToFloat(double v){
  98. BigDecimal b = new BigDecimal(v);
  99. return b.floatValue();
  100. }
  101. /**
  102. * 提供精确的类型转换(Int)不进行四舍五入
  103. * @param v 需要被转换的数字
  104. * @return 返回转换结果
  105. */
  106. public static int convertsToInt(double v){
  107. BigDecimal b = new BigDecimal(v);
  108. return b.intValue();
  109. }
  110. /**
  111. * 提供精确的类型转换(Long)
  112. * @param v 需要被转换的数字
  113. * @return 返回转换结果
  114. */
  115. public static long convertsToLong(double v){
  116. BigDecimal b = new BigDecimal(v);
  117. return b.longValue();
  118. }
  119. /**
  120. * 返回两个数中大的一个值
  121. * @param v1 需要被对比的第一个数
  122. * @param v2 需要被对比的第二个数
  123. * @return 返回两个数中大的一个值
  124. */
  125. public static double returnMax(double v1,double v2){
  126. BigDecimal b1 = new BigDecimal(v1);
  127. BigDecimal b2 = new BigDecimal(v2);
  128. return b1.max(b2).doubleValue();
  129. }
  130. /**
  131. * 返回两个数中小的一个值
  132. * @param v1 需要被对比的第一个数
  133. * @param v2 需要被对比的第二个数
  134. * @return 返回两个数中小的一个值
  135. */
  136. public static double returnMin(double v1,double v2){
  137. BigDecimal b1 = new BigDecimal(v1);
  138. BigDecimal b2 = new BigDecimal(v2);
  139. return b1.min(b2).doubleValue();
  140. }
  141. /**
  142. * 精确对比两个数字
  143. * @param v1 需要被对比的第一个数
  144. * @param v2 需要被对比的第二个数
  145. * @return 如果两个数一样则返回0,如果第一个数比第二个数大则返回1,反之返回-1
  146. */
  147. public static int compareTo(double v1,double v2){
  148. BigDecimal b1 = new BigDecimal(v1);
  149. BigDecimal b2 = new BigDecimal(v2);
  150. return b1.compareTo(b2);
  151. }
  152. }

原理推测应该是把小数扩展倍数为整数吧,因为整数不会有精度问题。

 560

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2