zoukankan      html  css  js  c++  java
  • Java中的浮点数-科学计数法-加减乘除

      上次,提到“元转分”这个浮点数问题,boss倾向于手动把1.23元这种格式,转换成123分。
      
      但实际上,浮点数很容易遇到精度问题。
      
      比如,System.out.println(4.015 * 1000);结果就不会是4015。
      
      以前,总结的元转分的问题,没能考虑到所有的场景,今天补充点上次遗漏的。
      
      -5.09,如果金额是负数,应该是-500-9=-509,而不是-500+9=-441,这是上次的一个超级bug。
      
      另外,需要还有一个超级bug,“1045189788”转换成double类型的元时,结果变成了1.04。
      
      debug了好久,才发现以前代码的漏洞。
      
      1045189788这种比较大的浮点数,在传递过程中,是“科学计数法”表示的,类似“1.04E”,
      所以,最后转换出了问题。
      
      其实,我一直不建议boss采用这种人工截取计算的方式,需要考虑的场景太复杂,建议使用JDK内置的BigDecimal。
      
      经过实践,发现很不错。
      
      可以用double、string等多种原始类型,构造BigDecimal,再进行四则运算。
      
      使用BigDecimal的关键是,控制“标度”即“精度”,scale。
      
      算术运算结果的首选标度  运算 结果的首选标度 
    加 max(addend.scale(), augend.scale()) 
    减 max(minuend.scale(), subtrahend.scale()) 
    乘 multiplier.scale() + multiplicand.scale() 
    除 dividend.scale() - divisor.scale() 


      下面这个工具类,是从网上copy的,还是非常有价值的。
      
      import java.math.BigDecimal;


    /**
     * 消除加减乘除的精度,解决Float与Double类型进度不准确的问题.
     */
    public class DoubleUtil {
    /**
    * 加法运算

    * @param v1
    * @param v2
    * @return
    */
    public static double add(double v1, double v2) {
    BigDecimal b1 = new BigDecimal(Double.toString(v1));
    BigDecimal b2 = new BigDecimal(Double.toString(v2));
    return b1.add(b2).doubleValue();
    }


    /**
    * 减法运算

    * @param v1
    * @param v2
    * @return
    */
    public static double sub(double v1, double v2) {
    BigDecimal b1 = new BigDecimal(Double.toString(v1));
    BigDecimal b2 = new BigDecimal(Double.toString(v2));
    return b1.subtract(b2).doubleValue();
    }


    /**
    * 乘法运算

    * @param v1
    * @param v2
    * @return
    */
    public static double mul(double v1, double v2) {
    BigDecimal b1 = new BigDecimal(Double.toString(v1));
    BigDecimal b2 = new BigDecimal(Double.toString(v2));
    return b1.multiply(b2).doubleValue();
    }


    /**
    * 除法运算

    * @param v1
    *            被除数
    * @param v2
    *            除数
    * @return 商
    */
    public static double div(double v1, double v2) {
    BigDecimal b1 = new BigDecimal(Double.toString(v1));
    BigDecimal b2 = new BigDecimal(Double.toString(v2));
    return b1.divide(b2).doubleValue();
    }


    /**
    * 除法运算

    * @param v1
    *            被除数
    * @param v2
    *            除数
    * @return 商和余数
    */
    public static BigDecimal[] divideAndRemainder(double v1, double v2) {
    BigDecimal b1 = new BigDecimal(Double.toString(v1));
    BigDecimal b2 = new BigDecimal(Double.toString(v2));
    BigDecimal[] arr = b1.divideAndRemainder(b2);
    return arr;
    }


    /**
    * 求商(向下舍入)

    * @param v1
    * @param v2
    * @return
    */
    public static BigDecimal divideToIntegralValue(double v1, double v2) {
    BigDecimal b1 = new BigDecimal(Double.toString(v1));
    BigDecimal b2 = new BigDecimal(Double.toString(v2));
    System.out.println("------------");
    return b1.divideToIntegralValue(b2);
    }


    public static void main(String[] args) {
    testUnPrecision();
    System.out.println("----------使用BigDecimal消除精度影响------------ "
    + DoubleUtil.add(0.05, 0.01));
    System.out.println(DoubleUtil.sub(1.0, 0.54));
    System.out.println(DoubleUtil.mul(4.015, 1000));
    System.out.println(DoubleUtil.div(12.3, 10));
    // 得到商和余数
    BigDecimal[] arr = DoubleUtil.divideAndRemainder(12.3, 10);
    System.out.println("得到商和余数");
    for (BigDecimal bigDecimal : arr) {
    System.out.println(bigDecimal);
    }
    System.out.println(DoubleUtil.divideToIntegralValue(4.5, 2));
    }


    /**
    * 不准确问题示例
    */
    private static void testUnPrecision() {
    System.out.println("--------Java自身的Double类型有精度损失----------");
    System.out.println(0.05 + 0.01);
    System.out.println(1.0 - 0.54);
    System.out.println(4.015 * 1000);
    System.out.println(12.3 / 100);
    }
    }

  • 相关阅读:
    自定义组件要加@click方法
    绑定样式
    647. Palindromic Substrings
    215. Kth Largest Element in an Array
    448. Find All Numbers Disappeared in an Array
    287. Find the Duplicate Number
    283. Move Zeroes
    234. Palindrome Linked List
    202. Happy Number
    217. Contains Duplicate
  • 原文地址:https://www.cnblogs.com/qitian1/p/6462860.html
Copyright © 2011-2022 走看看