java 金额计算不能用float、doube!!!!必须用BigDecimal

来源:互联网 发布:培训交互设计师知乎 编辑:程序博客网 时间:2024/05/01 19:12

金额计算不能用doube!!!!

金额计算不能用doube!!!!

金额计算不能用doube!!!!

重要的事情讲三遍。哈,金额计算必须用BigDecimal,下面对比一下用double 跟BigDecimal的区别,这里为了方便我直接调用工具类MoneyUtil,最后再来看工具类怎么实现

1.出现科学计数法:

[java] view plain copy
  1. double d1 = 0.00000000000000001;  
  2. Log.v("zyl""d1:"+d1);  
[java] view plain copy
  1. Log.v("zyl""d1:"+MoneyUtil.formatMoney(d1+""));  

控制台输出结果:d1:1.0E-17

                           d1:0.00000000000000001000

2.计算金额不准确,丢失精度:

[java] view plain copy
  1. double d1 = 11540;  
  2. double d2 = 0.35;  
  3. Log.v("zyl""result:"+(d1*d2));  
  4. Log.v("zyl""result2:"+MoneyUtil.moneyMul(d1+"", d2+""));  
控制台输出结果:

result:4038.9999999999995
result2:4039.00000000000000000000 (正确答案)

3.避免发生强转错误

这个虽然跟自己粗心有关,但实际在项目应用的时候,往往数据既需要计算,又需要展示,比如你在计算单价跟数量相乘的是,一般我们会用int 跟 double ,然后展示的时候又需要字符串。好了,此时你把它转为字符串了,但又需要你拿着刚才的数字去做运算。此时你又要考虑你拿到的字段数据是字符串还是int 还是 double,万一拿错了就出现强转错误了,尤其在项目中用到了非常多的数据,这样的处理方式是极其混乱与不推荐的。

正确的做法是:统一用字符串保存,然后在工具类里面将字符串进行格式化为BigDecimal,这样既解决了前面3个问题,又能直接放在UI上展示,是不是觉得略爽?

=====================================此处是分割线======================================


现在来看看这个所谓的BigDecimal用法,其实,非常简单!

1.有需要确切保留小数点后几位的话,需要先new一个格式转换器

DecimalFormat fnum = new DecimalFormat("##0.00000000000000000000");

2.BigDecimal的使用:

BigDecimal value = new BigDecimal(“0.00000001”);

再格式化一下

        String value  = fnum.format(value);

完了。就这么简单,最后奉献上自己珍藏的多年的工具类:包含BigDecimal类型的加减乘除以及大小比较,还有将金额数据加逗号格式化后显示,例如 “123456”显示为“123,456”

[java] view plain copy
  1. package com.example.test;  
  2.   
  3. import android.util.Log;  
  4.   
  5. import java.math.BigDecimal;  
  6. import java.text.DecimalFormat;  
  7.   
  8. /** 
  9.  * 金额工具类,主要是金额的格式化,金额的加、减  
  10.  * @author Tiny 
  11.  * 
  12.  */  
  13. public class MoneyUtil {  
  14.   
  15.     public static DecimalFormat fnum = new DecimalFormat("##0.00000000000000000000");  
  16.       
  17.     /** 
  18.      * 格式化金额 
  19.      * @param value 
  20.      * @return 
  21.      */  
  22.     public static String formatMoney(String value){  
  23.         if(value == null || value == "" ){  
  24.             value = "0.00";  
  25.         }  
  26.         return fnum.format(new BigDecimal(value));  
  27.     }  
  28.       
  29.       
  30.       
  31.     /** 
  32.      * 金额相加 
  33.      * @param valueStr 基础值 
  34.      * @param minusValueStr 被加数 
  35.      * @return 
  36.      */  
  37.     public static String moneyAdd(String valueStr,String addStr){  
  38.         BigDecimal value = new BigDecimal(valueStr);  
  39.         BigDecimal augend = new BigDecimal(addStr);  
  40.         return fnum.format(value.add(augend));  
  41.     }  
  42.       
  43.     /** 
  44.      * 金额相加 
  45.      * @param valueStr 基础值 
  46.      * @param minusValueStr 被加数 
  47.      * @return 
  48.      */  
  49.     public static BigDecimal moneyAdd(BigDecimal value,BigDecimal augend){  
  50.         return value.add(augend);  
  51.     }  
  52.       
  53.     /** 
  54.      * 金额相减 
  55.      * @param valueStr 基础值 
  56.      * @param minusValueStr 减数 
  57.      * @return 
  58.      */  
  59.     public static String moneySub(String valueStr,String minusStr){  
  60.         BigDecimal value= new BigDecimal(valueStr);  
  61.         BigDecimal subtrahend = new BigDecimal(minusStr);  
  62.         return fnum.format(value.subtract(subtrahend));  
  63.     }  
  64.       
  65.     /** 
  66.      * 金额相减 
  67.      * @param value 基础值 
  68.      * @param subtrahend 减数 
  69.      * @return 
  70.      */  
  71.     public static BigDecimal moneySub(BigDecimal value,BigDecimal subtrahend){  
  72.         return value.subtract(subtrahend);  
  73.     }  
  74.       
  75.       
  76.     /** 
  77.      * 金额相乘 
  78.      * @param valueStr 基础值 
  79.      * @param minusValueStr 被乘数 
  80.      * @return 
  81.      */  
  82.     public static String moneyMul(String valueStr,String mulStr){  
  83.         BigDecimal value = new BigDecimal(valueStr);  
  84.         BigDecimal mulValue = new BigDecimal(mulStr);  
  85.         return fnum.format(value.multiply(mulValue));  
  86.     }  
  87.       
  88.     /** 
  89.      * 金额相乘 
  90.      * @param value 基础值 
  91.      * @param mulValue 被乘数 
  92.      * @return 
  93.      */  
  94.     public static BigDecimal moneyMul(BigDecimal value,BigDecimal mulValue){  
  95.         return value.multiply(mulValue);  
  96.     }  
  97.       
  98.     /** 
  99.      * 金额相除 <br/> 
  100.      * 精确小位小数 
  101.      * @param valueStr 基础值 
  102.      * @param minusValueStr 被乘数 
  103.      * @return 
  104.      */  
  105.     public static String moneydiv(String valueStr,String divideStr){  
  106.         BigDecimal value = new BigDecimal(valueStr);  
  107.         BigDecimal divideValue = new BigDecimal(divideStr);  
  108.         return fnum.format(value.divide(divideValue, 2, BigDecimal.ROUND_HALF_UP));  
  109.     }  
  110.       
  111.     /** 
  112.      * 金额相除 <br/> 
  113.      * 精确小位小数 
  114.      * @param value 基础值 
  115.      * @param divideValue 被乘数 
  116.      * @return 
  117.      */  
  118.     public static BigDecimal moneydiv(BigDecimal value,BigDecimal divideValue){  
  119.         return value.divide(divideValue, 2, BigDecimal.ROUND_HALF_UP);  
  120.     }  
  121.       
  122.       
  123.     /** 
  124.      * 值比较大小 
  125.      * <br/>如果valueStr大于等于compValueStr,则返回true,否则返回false 
  126.      *  true 代表可用余额不足 
  127.      * @param valueStr (需要消费金额) 
  128.      * @param compValueStr (可使用金额) 
  129.      * @return  
  130.      */  
  131.     public static boolean moneyComp(String valueStr,String compValueStr){  
  132.         BigDecimal value = new BigDecimal(valueStr);  
  133.         BigDecimal compValue = new BigDecimal(compValueStr);  
  134.         //0:等于    >0:大于    <0:小于  
  135.         int result = value.compareTo(compValue);  
  136.         if(result >= 0){  
  137.             return true;  
  138.         }else{  
  139.             return false;  
  140.         }  
  141.     }  
  142.       
  143.     /** 
  144.      * 值比较大小 
  145.      * <br/>如果valueStr大于等于compValueStr,则返回true,否则返回false 
  146.      *  true 代表可用余额不足 
  147.      * @param valueStr (需要消费金额) 
  148.      * @param compValueStr (可使用金额) 
  149.      * @return  
  150.      */  
  151.     public static boolean moneyComp(BigDecimal valueStr,BigDecimal compValueStr){  
  152.         //0:等于    >0:大于    <0:小于  
  153.         int result = valueStr.compareTo(compValueStr);  
  154.         if(result >= 0){  
  155.             return true;  
  156.         }else{  
  157.             return false;  
  158.         }  
  159.     }  
  160.       
  161.     /** 
  162.      * 金额乘以,省去小数点 
  163.      * @param valueStr 基础值 
  164.      * @return 
  165.      */  
  166.     public static String moneyMulOfNotPoint (String valueStr, String divideStr){  
  167.         BigDecimal value = new BigDecimal(valueStr);  
  168.         BigDecimal mulValue = new BigDecimal(divideStr);  
  169.         valueStr = fnum.format(value.multiply(mulValue));  
  170.         return fnum.format(value.multiply(mulValue)).substring(0, valueStr.length()-3);  
  171.     }  
  172.   
  173.     /** 
  174.      * 给金额加逗号切割 
  175.      * @param str 
  176.      * @return 
  177.      */  
  178.     public static String addComma(String str) {  
  179.         try {  
  180.             String banNum = "";  
  181.             if (str.contains(".")) {  
  182.                 String[] arr = str.split("\\.");  
  183.                 if (arr.length == 2) {  
  184.                     str = arr[0];  
  185.                     banNum = "." + arr[1];  
  186.                 }  
  187.             }  
  188.             // 将传进数字反转  
  189.             String reverseStr = new StringBuilder(str).reverse().toString();  
  190.             String strTemp = "";  
  191.             for (int i = 0; i < reverseStr.length(); i++) {  
  192.                 if (i * 3 + 3 > reverseStr.length()) {  
  193.                     strTemp += reverseStr.substring(i * 3, reverseStr.length());  
  194.                     break;  
  195.                 }  
  196.                 strTemp += reverseStr.substring(i * 3, i * 3 + 3) + ",";  
  197.             }  
  198.             // 将[789,456,] 中最后一个[,]去除  
  199.             if (strTemp.endsWith(",")) {  
  200.                 strTemp = strTemp.substring(0, strTemp.length() - 1);  
  201.             }  
  202.             // 将数字重新反转  
  203.             String resultStr = new StringBuilder(strTemp).reverse().toString();  
  204.             resultStr += banNum;  
  205.             return resultStr;  
  206.         }catch(Exception e){  
  207.             return str;  
  208.         }  
  209.   
  210.     }  
  211.   
  212. }  

阅读全文
0 0