zoukankan      html  css  js  c++  java
  • Java 算术运算

    有时候可能会碰到需要计算非常大的数,比如7777777777777777777777777*3333333333333333333333333333,这样的计算需要显然不能用之前的方式来进行。我们不能用任何的数据类型来装下这么大的数,它已经操作了int、float、double的数据类型的范围。那么如何解决这样的计算需求呢?这时候,就需要进行大数操作。

    在java.math这个包中有两个进行大数操作的类:java.math.BigInteger和java.math.BigDecimal。从名字上可以知道这两个类的作用了吧。很明显,前者是进行整数的大数操作的,后者是进行小数的大数操作的。下面来看一下实例。

    实例1:获取两数相除的商和余数

     import java.math.BigInteger;
    
    public classBigIntegerDemo01 {
    
        public static voidmain(String[] args){
    
           String num1="88379348888888478403839479";
    
           String num2="838777777333333333337";
    
          
    
           BigInteger big1=newBigInteger(num1);
    
           BigInteger big2=newBigInteger(num2);
    
           System.out.println(big1.add(big2));//加法操作
    
           System.out.println(big1.subtract(big2));//加法操作
    
           System.out.println(big1.multiply(big2));//乘法操作
    
           System.out.println(big1.divide(big2));//除法操作
    
           BigInteger[] result=big1.divideAndRemainder(big2);
    
           System.out.println(big1.toString()+"/"+big2.toString()+"的商:"+result[0]);
    
           System.out.println(big1.toString()+"/"+big2.toString()+"的余数:"+result[1]);
    
        }
    
    }

    构造方法public BigInteger(String val)是 将 BigInteger 的十进制字符串表示形式转换为 BigInteger。大整数操作可以像其它类型的数据一样进行加法、减法、乘法、除法等操作。

    需要特别说明的是除法操作。public BigInteger divide(BigInteger val)这个方法只能得到一个“商“,要想的到余数需要用public BigInteger[] divideAndRemainder(BigInteger val)这个方法。divideAndRemainder()这个方法返回的是存储有”商“和”余数“的BigInteger数组。

    实例2:

     package cn.tty.math;
    
    import java.math.BigDecimal;
    
    public class BigDecimalDemo02 {
    
        public static void main(String[] args) {
    
           String num1="84995.333333333323";
    
           String num2="894.99";
    
           //保留5位小数
    
           System.out.println(BigDecimalDemo02.round(BigDecimalDemo02.add(num1, num2), 5));
    
           //保留4位小数
    
           System.out.println(BigDecimalDemo02.round(BigDecimalDemo02.subtract(num1, num2), 4));
    
           //保留3位小数
    
           System.out.println(BigDecimalDemo02.round(BigDecimalDemo02.multiply(num1, num2), 3));
    
           //保留2位小数
    
           System.out.println(BigDecimalDemo02.divide(num1, num2,2));
    
        }
    
        public static double add(String num1,String num2){
    
           //将 BigDecimal 的字符串表示形式转换为BigDecimal
    
           BigDecimal b1=new BigDecimal(num1);
    
           BigDecimal b2=new BigDecimal(num2);
    
           returnb1.add(b2).doubleValue();
    
        }
    
        public static double subtract(String num1,String num2){
    
           //将 BigDecimal 的字符串表示形式转换为BigDecimal
    
           BigDecimal b1=new BigDecimal(num1);
    
           BigDecimal b2=new BigDecimal(num2);
    
           returnb1.subtract(b2).doubleValue();
    
        }
    
        public static double multiply(String num1,String num2){
    
           //将 BigDecimal 的字符串表示形式转换为BigDecimal
    
           BigDecimal b1=new BigDecimal(num1);
    
           BigDecimal b2=new BigDecimal(num2);
    
           returnb1.multiply(b2).doubleValue();
    
        }
    
        public static double divide(String num1,String num2,int scale){
    
           BigDecimal b1=new BigDecimal(num1);
    
           BigDecimal b2=new BigDecimal(num2);
    
           //下面的“2”表示需要保留的小数位数,“BigDecimal.ROUND_HALF_UP”常量表示的是四舍五入的模式
    
           returnb1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
    
          
    
        }
    
       
    
        public static double round(doublenum1,int scale){
    
           BigDecimal big1=new BigDecimal(num1);
    
           BigDecimal big2=new BigDecimal(1);
    
           returnbig1.divide(big2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();//任何数除于1都等于本身
    
        }
    
    }

    上面的例子重新包装了BigDecimal的加减乘除操作,是这些方法的使用更符合本例的需要。加减乘的操作就不用多说了,很直接,很简单,需要说明的还是除法操作。 

    BigDecimal的除法重载了很多。其中有一种是public BigDecimal divide(BigDecimal divisor,int scale,RoundingMode roundingMode)。这种方法指定了保留的小数位数(scale)和四舍五入的模式(roundingMode)。比如,“ROUND_HALF_DOWN“的模式表示向最接近的数字舍入,如果与两个相邻数字的距离相等,则为上舍入的舍入模式。

    //下面的操作不涉及大数操作的内容,但涉及到保留小数位数
    
           doublex=874.748;
    
           doubley=893.32;
    
           doublez=x*y;
    
           System.out.println("x * Y = "+z);
    
           System.out.println("x * Y = "+(int)(z*10)/10.0);//保留1为小数
    
           System.out.println("x * Y = "+(int)(z*100)/100.0);//保留2为小数
    
           System.out.println("x * Y = "+(int)(z*1000)/1000.0);//保留3为小数

    这种方式并不能完全指定四舍五入的小数位数,可以称之为“伪四舍五入“,因为这某种巧合的情况下,它并不能很好的实现指定小数位数的功能。比如x=874.738,y=893.32那么 z = 781420.9501600001。(int)(z*1000)/1000.0的输出结果仍为”781420.95“,并没有预想的保留3位小数。原因很简单,z*1000=781420950. 1600001,(int)(z*1000)= 781420950,那么(int)(z*1000)/1000.0=781420.95。因为末位是0,因此被舍掉了。

    虽然这种方式的保留小数位数的方式不保险,但这种方式简单便捷,在要求并不严苛的情况下可以使用。

    还有个四舍五入的方法,在java.lang.Math类中:

    public static long round(double a)

    public static int round(float a)

    显然,这两个方法返回的数将是整型数据,并不会保留任何小数。

     //使用java.text.DecimalFormat类实现四舍五入和保留指定位数的小数
    
    packagecn.tty.format;
    
    importjava.text.DecimalFormat;
    
    public classDecimalFormatDemo02 {
    
        public staticString round(String pattern,double value){
    
           DecimalFormat formatter=newDecimalFormat(pattern);
    
           String rv=formatter.format(value);
    
           return rv;
    
        }
    
        public static voidmain(String[] args){
    
           //指定模式:保留2为小数
    
           String roundedValue=DecimalFormatDemo02.round("####.00",838.666);//保留两位小数
    
           System.out.println(roundedValue);
    
        }
    
    }
    import java.math.BigDecimal;
    import java.text.DecimalFormat;
    
    public final class ArithUtil
    {
      private static final int DEF_DIV_SCALE = 10;
    
      public static boolean isDoubleNotGreater(double d1, double d2)
      {
        boolean bn = false;
        BigDecimal b1 = new BigDecimal(Double.toString(d1));
        BigDecimal b2 = new BigDecimal(Double.toString(d2));
    
        if (b1.compareTo(b2) <= 0)
          bn = true;
        else {
          bn = false;
        }
    
        return bn;
      }
    
      public static boolean isDoubleNotLess(double d1, double d2)
      {
        boolean bn = false;
        BigDecimal b1 = new BigDecimal(Double.toString(d1));
        BigDecimal b2 = new BigDecimal(Double.toString(d2));
    
        if (b1.compareTo(b2) >= 0)
          bn = true;
        else {
          bn = false;
        }
    
        return bn;
      }
    
      public static boolean isDoubleEqual(double d1, double d2)
      {
        boolean bn = false;
        BigDecimal b1 = new BigDecimal(Double.toString(d1));
        BigDecimal b2 = new BigDecimal(Double.toString(d2));
    
        if (b1.compareTo(b2) == 0)
          bn = true;
        else {
          bn = false;
        }
    
        return bn;
      }
    
      public static double add(double d1, double d2)
      {
        BigDecimal b1 = new BigDecimal(Double.toString(d1));
        BigDecimal b2 = new BigDecimal(Double.toString(d2));
        return b1.add(b2).doubleValue();
      }
    
      public static double sub(double d1, double d2)
      {
        BigDecimal b1 = new BigDecimal(Double.toString(d1));
        BigDecimal b2 = new BigDecimal(Double.toString(d2));
        return b1.subtract(b2).doubleValue();
      }
    
      public static double mul(double d1, double d2)
      {
        BigDecimal b1 = new BigDecimal(Double.toString(d1));
        BigDecimal b2 = new BigDecimal(Double.toString(d2));
        return b1.multiply(b2).doubleValue();
      }
    
      public static double div(double d1, double d2, int scale)
      {
        if (scale < 0)
          throw new IllegalArgumentException("The scale must be a positive integer or zero");
    
        BigDecimal b1 = new BigDecimal(Double.toString(d1));
        BigDecimal b2 = new BigDecimal(Double.toString(d2));
        return b1.divide(b2, scale, 4).doubleValue(); //4 是ROUND_HALF_UP,也就是最常见的四舍五入,大于一般则向上舍入,否则向下舍入
      }
    
      public static double div(double d1, double d2)
      {
        return div(d1, d2, 10);
      }
    
      public static double round(double d, int scale)
      {
        if (scale < 0)
          throw new IllegalArgumentException("The scale must be a positive integer or zero");
    
        BigDecimal b = new BigDecimal(Double.toString(d));
        BigDecimal one = BigDecimal.ONE;
        return b.divide(one, scale, 4).doubleValue();
      }
    
      public static String genPattern(String subStr, int n)
      {
        StringBuffer temp = new StringBuffer();
        while (n > 0) {
          if ((subStr.trim().equals("#")) && (n == 1))
            temp.append('0');
          else
            temp.append(subStr);
    
          --n;
        }
        return temp.toString();
      }
    
      public static String formatDouble(double number, int intPart, int decPart)
      {
        return new DecimalFormat(genPattern("#", intPart) + "." + genPattern("0", decPart)).format(number);
      }
    
      public static String formatDecimal(BigDecimal number, int intPart, int decPart)
      {
        return new DecimalFormat(genPattern("#", intPart) + "." + genPattern("0", decPart)).format(number);
      }
    
      public static String double2str(double amount, int length)
      {
        String strAmt = Double.toString(amount);
        int pos = strAmt.indexOf(46);
    
        if ((pos != -1) && (strAmt.length() > length + pos + 1)) {
          strAmt = strAmt.substring(0, pos + length + 1);
        }
    
        return strAmt;
      }
    }

    DecimalFormat 是 NumberFormat 的一个具体子类,用于格式化十进制数字。

    DecimalFormat 包含一个模式 和一组符号
    符号含义:
    0 一个数字
    # 一个数字,不包括 0
    . 小数的分隔符的占位符
    , 分组分隔符的占位符
    ; 分隔格式。
    - 缺省负数前缀。
    % 乘以 100 和作为百分比显示
    ? 乘以 1000 和作为千进制货币符显示;用货币符号代替;如果双写,用
    国际货币符号代替。如果出现在一个模式中,用货币十进制分隔符代
    替十进制分隔符。
    X 前缀或后缀中使用的任何其它字符,用来引用前缀或后缀中的特殊字符。
    例子:

    DecimalFormat df1 = new DecimalFormat("0.0"); 
    
    DecimalFormat df2 = new DecimalFormat("#.#"); 
    
    DecimalFormat df3 = new DecimalFormat("000.000"); 
    
    DecimalFormat df4 = new DecimalFormat("###.###"); 
    
    System.out.println(df1.format(12.34)); 
    
    System.out.println(df2.format(12.34)); 
    
    System.out.println(df3.format(12.34)); 
    
    System.out.println(df4.format(12.34)); 

    结果:
    12.3
    12.3
    012.340
    12.34

  • 相关阅读:
    作为面试官,中级应用级Web前端我会问什么问题
    vue相关项目提示 Failed to resolve Loader: sass-loader
    [Vue warn]: Error in beforeDestroy hook: "Error: [ElementForm]unpected width
    JVM调优方法
    HTTP协议—— 简单认识TCP/IP协议
    关于软件的版本管理
    开源数据库
    PE51
    浅谈限流组件的应用和设计原则
    Spring+AspectJ框架使用实践
  • 原文地址:https://www.cnblogs.com/mingforyou/p/2266771.html
Copyright © 2011-2022 走看看