JAVA从零开始17_常用API BigInteger BigDecima 正则表达式

本文详细介绍了Java中的BigInteger和BigDecimal类,用于处理大整数和高精度浮点数计算,强调了它们在加密、金融计算和高精度计算中的应用。同时,文章探讨了银行家算法,这是一种避免舍入误差的策略。最后,文章还简要提及了Java中的正则表达式及其在字符串模式匹配、验证和替换中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、BigInteger

Java中的BigInteger类是一个不可变的任意精度的整数类,它提供了对大整数进行操作的方法,包括算术运算、位操作、比较等。与Java的基本整数类型(如intlong)相比,BigInteger类可以处理非常大的整数,而不会溢出。但是,BigInteger的运算速度会慢于基本整数类型,因为它需要使用数组和更复杂的算法来处理大整数。

以下是BigInteger类中的一些常用方法:

  1. 构造方法:BigInteger类提供了多种构造方法,例如BigInteger(String val)BigInteger(byte[] val),用于根据字符串或字节数组创建一个BigInteger对象。

  2. 算术运算:BigInteger类提供了一系列的算术运算方法,例如add(BigInteger val)subtract(BigInteger val)multiply(BigInteger val)divide(BigInteger val)remainder(BigInteger val),用于对大整数进行加法、减法、乘法、除法和取余运算。

  3. 位操作:BigInteger类提供了位操作方法,例如and(BigInteger val)or(BigInteger val)xor(BigInteger val)not()shiftLeft(int n)shiftRight(int n),用于对大整数进行按位与、按位或、按位异或、按位非、左移和右移操作。

  4. 比较:BigInteger类提供了compareTo(BigInteger val)方法,用于比较两个BigInteger对象的大小。

  5. 基本数学运算:BigInteger类提供了一些基本数学运算方法,例如pow(int exponent)(求幂)、gcd(BigInteger val)(求最大公约数)、abs()(求绝对值)和negate()(求负值)。

  6. 素数相关操作:BigInteger类提供了素数相关的方法,例如isProbablePrime(int certainty)(测试大整数是否可能为素数)和nextProbablePrime()(查找大于当前大整数的下一个可能的素数)。

以下是BigInteger类的使用示例:

import java.math.BigInteger;

public class BigIntegerExample {
    public static void main(String[] args) {
        BigInteger a = new BigInteger("12345678901234567890");
        BigInteger b = new BigInteger("98765432109876543210");

        BigInteger sum = a.add(b);
        BigInteger difference = a.subtract(b);
        BigInteger product = a.multiply(b);
        BigInteger quotient = a.divide(b);
        BigInteger remainder = a.remainder(b);

        System.out.println("Sum: " + sum);
        System.out.println("Difference: " + difference);
        System.out.println("Product: " + product);
        System.out.println("Quotient: " + quotient);
        System.out.println("Remainder: " + remainder);
    }
}

在实际应用中,BigInteger类通常用于处理加密、大数计算、高精度计算等需要处理非常大整数的场景。

以下是一些使用场景的示例:

  1. 加密和安全
    BigInteger类在加密算法(如RSA、ElGamal等)中经常被用到,因为这些算法通常涉及到大整数的运算。例如,在RSA加密算法中,公钥和私钥都是由大整数构成的,而加密和解密过程需要进行大整数的幂运算和模运算。

    import java.math.BigInteger;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.NoSuchAlgorithmException;
    
    public class RSAExample {
        public static void main(String[] args) throws NoSuchAlgorithmException {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(2048);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
    
            BigInteger publicKeyModulus = new BigInteger(1, keyPair.getPublic().getEncoded());
            BigInteger privateKeyModulus = new BigInteger(1, keyPair.getPrivate().getEncoded());
    
            System.out.println("Public Key Modulus: " + publicKeyModulus);
            System.out.println("Private Key Modulus: " + privateKeyModulus);
        }
    }
    
  2. 高精度计算
    在需要进行高精度计算的场景中,BigInteger类可以用于确保精度不受限制。例如,计算大整数阶乘:

    import java.math.BigInteger;
    
    public class FactorialExample {
        public static void main(String[] args) {
            int n = 100;
            BigInteger factorial = BigInteger.ONE;
    
            for (int i = 2; i <= n; i++) {
                factorial = factorial.multiply(BigInteger.valueOf(i));
            }
    
            System.out.println(n + "! = " + factorial);
        }
    }
    
  3. 大数运算
    在处理大数运算时,BigInteger类可以确保不会发生溢出。例如,计算Fibonacci数列中的大数项:

    import java.math.BigInteger;
    
    public class FibonacciExample {
        public static void main(String[] args) {
            int n = 1000;
            BigInteger a = BigInteger.ZERO;
            BigInteger b = BigInteger.ONE;
    
            for (int i = 2; i <= n; i++) {
                BigInteger next = a.add(b);
                a = b;
                b = next;
            }
    
            System.out.println("Fibonacci(" + n + ") = " + b);
        }
    }
    

这些示例展示了BigInteger类在实际使用中的一些常见场景。通过使用BigInteger,可以确保处理大整数时不会发生溢出,并在需要高精度计算时保持精确。


二、BigDecima

Java中的BigDecimal类是一个不可变的任意精度的十进制数类,用于处理高精度浮点数的计算。与Java的基本浮点类型(如floatdouble)相比,BigDecimal类可以提供精确的小数运算,避免因浮点数表示和舍入误差而导致的不精确计算。但是,BigDecimal的运算速度会慢于基本浮点类型,因为它需要使用数组和更复杂的算法来处理高精度数值。

以下是BigDecimal类中的一些常用方法:

  1. 构造方法:BigDecimal类提供了多种构造方法,例如BigDecimal(String val)BigDecimal(double val)BigDecimal(BigInteger val),用于根据字符串、双精度浮点数或大整数创建一个BigDecimal对象。

  2. 算术运算:BigDecimal类提供了一系列的算术运算方法,例如add(BigDecimal val)subtract(BigDecimal val)multiply(BigDecimal val)divide(BigDecimal val, int scale, RoundingMode roundingMode),用于对高精度浮点数进行加法、减法、乘法和除法运算。

  3. 比较:BigDecimal类提供了compareTo(BigDecimal val)方法,用于比较两个BigDecimal对象的大小。

  4. 舍入和缩放:BigDecimal类提供了setScale(int scale, RoundingMode roundingMode)方法,用于设置小数点后的位数并对超出部分进行舍入。此外,还提供了round(MathContext mc)方法,用于根据给定的数学上下文对BigDecimal对象进行舍入。

  5. 基本数学运算:BigDecimal类提供了一些基本数学运算方法,例如pow(int n)(求幂)和abs()(求绝对值)。

以下是BigDecimal类的使用示例:

import java.math.BigDecimal;
import java.math.RoundingMode;

public class BigDecimalExample {
    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("12345.6789");
        BigDecimal b = new BigDecimal("9876.54321");

        BigDecimal sum = a.add(b);
        BigDecimal difference = a.subtract(b);
        BigDecimal product = a.multiply(b);
        BigDecimal quotient = a.divide(b, 10, RoundingMode.HALF_UP);

        System.out.println("Sum: " + sum);
        System.out.println("Difference: " + difference);
        System.out.println("Product: " + product);
        System.out.println("Quotient: " + quotient);
    }
}

在实际应用中,BigDecimal类通常用于处理金融计算、科学计算、货币计算等需要进行高精度浮点数计算的场景。

以下是一些使用场景的示例:

  1. 金融计算
    在金融领域,精确的数值计算是非常重要的。BigDecimal类可用于处理金融计算,避免因浮点数表示和舍入误差导致的计算不精确。例如,计算复利:

    import java.math.BigDecimal;
    import java.math.RoundingMode;
    
    public class CompoundInterest {
        public static void main(String[] args) {
            BigDecimal principal = new BigDecimal("10000");
            BigDecimal rate = new BigDecimal("0.05");
            int years = 5;
    
            BigDecimal amount = principal.multiply(rate.add(BigDecimal.ONE).pow(years)).setScale(2, RoundingMode.HALF_UP);
    
            System.out.println("Amount after " + years + " years: $" + amount);
        }
    }
    
  2. 货币计算
    在处理货币计算时,BigDecimal类可以确保精确表示货币值。例如,计算购物车中商品的总价:

    import java.math.BigDecimal;
    import java.math.RoundingMode;
    import java.util.HashMap;
    import java.util.Map;
    
    public class ShoppingCart {
        public static void main(String[] args) {
            Map<String, BigDecimal> items = new HashMap<>();
            items.put("item1", new BigDecimal("12.99"));
            items.put("item2", new BigDecimal("25.50"));
            items.put("item3", new BigDecimal("7.45"));
    
            BigDecimal totalPrice = BigDecimal.ZERO;
            for (BigDecimal price : items.values()) {
                totalPrice = totalPrice.add(price);
            }
    
            totalPrice = totalPrice.setScale(2, RoundingMode.HALF_UP);
            System.out.println("Total price: $" + totalPrice);
        }
    }
    
  3. 科学计算
    在进行科学计算时,BigDecimal类可以用于处理高精度浮点数计算,避免因舍入误差而导致的不精确计算。例如,计算圆周率:

    import java.math.BigDecimal;
    import java.math.MathContext;
    import java.math.RoundingMode;
    
    public class CalculatePi {
        public static void main(String[] args) {
            int precision = 100;
            MathContext mc = new MathContext(precision, RoundingMode.HALF_UP);
            BigDecimal pi = BigDecimal.ZERO;
            BigDecimal one = BigDecimal.ONE;
            BigDecimal two = new BigDecimal("2");
            BigDecimal four = new BigDecimal("4");
    
            for (int i = 0; i < precision; i++) {
                BigDecimal term1 = one.divide(two.pow(i * 2), mc);
                BigDecimal term2 = one.divide(four.multiply(new BigDecimal(i)).add(one), mc);
                BigDecimal term3 = one.divide(four.multiply(new BigDecimal(i)).add(three), mc);
    
                pi = pi.add(term1.multiply(term2.subtract(term3)));
            }
    
            pi = pi.multiply(two).setScale(precision, RoundingMode.HALF_UP);
            System.out.println("Pi: " + pi);
        }
    }
    

这些示例展示了BigDecimal类在实际应用中的一些使用场景:

  1. 在金融计算中,BigDecimal确保了计算复利时的数值精确性。
  2. 在货币计算中,BigDecimal能够确保计算购物车商品总价时的精确表示。
  3. 在科学计算中,BigDecimal用于计算圆周率,避免了因舍入误差导致的不精确计算。

这些示例只是BigDecimal类在实际应用中的一部分使用场景。在需要高精度浮点数计算的任何场合,BigDecimal都可以作为一个有力的工具来确保数值的精确表示和计算。


三、创建BigDecimal和BigInteger

创建BigDecimalBigInteger对象的方法相似,但在细节上有一些不同。以下是创建这两个类对象的常用方法:

  1. 创建BigDecimal对象

    BigDecimal类提供了多种构造方法,以便根据不同类型的参数创建对象。以下是一些常用的构造方法:

    • BigDecimal(String val):根据字符串创建一个BigDecimal对象。例如:

      BigDecimal a = new BigDecimal("12345.6789");
      
    • BigDecimal(double val):根据双精度浮点数创建一个BigDecimal对象。需要注意的是,这种方法可能会导致不精确的结果,因为双精度浮点数本身可能无法精确表示某些数值。例如:

      BigDecimal b = new BigDecimal(12345.6789);
      
    • BigDecimal(BigInteger val):根据大整数创建一个BigDecimal对象。例如:

      BigInteger bi = new BigInteger("123456789");
      BigDecimal c = new BigDecimal(bi);
      
  2. 创建BigInteger对象

    BigInteger类同样提供了多种构造方法,以便根据不同类型的参数创建对象。以下是一些常用的构造方法:

    • BigInteger(String val):根据字符串创建一个BigInteger对象。例如:

      BigInteger a = new BigInteger("123456789");
      
    • BigInteger(String val, int radix):根据指定基数的字符串创建一个BigInteger对象。例如:

      BigInteger b = new BigInteger("1A2B3C", 16);
      
    • BigInteger(byte[] val):根据字节数组创建一个BigInteger对象。例如:

      byte[] byteArray = {1, 2, 3, 4, 5};
      BigInteger c = new BigInteger(byteArray);
      

在创建BigDecimalBigInteger对象时,最大的细微差别在于创建BigDecimal对象时可以使用浮点数作为参数,而创建BigInteger对象时只能使用整数。此外,在创建BigInteger对象时,可以指定基数,而BigDecimal对象则默认使用十进制表示。


四、银行家算法

银行家算法(Bankers’ rounding)是一种舍入方法,主要用于避免在进行连续四舍五入操作时产生的系统性偏差。这种舍入方法的核心思想是:如果一个数的小数部分恰好为0.5,那么在舍入时应向最近的偶数舍入。具体规则如下:

  1. 如果小数部分大于0.5,则向上舍入。
  2. 如果小数部分小于0.5,则向下舍入。
  3. 如果小数部分等于0.5:
    • 如果整数部分为奇数,则向上舍入,使整数部分变为偶数。
    • 如果整数部分为偶数,则向下舍入,使整数部分保持为偶数。

以下是银行家算法的一些示例:

  • 0.5 舍入为 0(偶数)
  • 1.5 舍入为 2(偶数)
  • 2.5 舍入为 2(偶数)
  • 3.5 舍入为 4(偶数)
  • 4.5 舍入为 4(偶数)
  • 5.5 舍入为 6(偶数)

这种舍入方法的优点是在大量数据计算中,上舍入和下舍入的次数相当,从而避免了系统性偏差。这种方法在金融领域和计算机编程中被广泛使用。

在Java中,我们可以使用BigDecimal类的setScale()方法实现银行家算法,如下所示:

import java.math.BigDecimal;
import java.math.RoundingMode;

public class BankersRounding {
    public static void main(String[] args) {
        BigDecimal a = new BigDecimal("0.5");
        BigDecimal b = new BigDecimal("1.5");
        BigDecimal c = new BigDecimal("2.5");
        BigDecimal d = new BigDecimal("3.5");

        System.out.println("0.5 rounded: " + a.setScale(0, RoundingMode.HALF_EVEN));
        System.out.println("1.5 rounded: " + b.setScale(0, RoundingMode.HALF_EVEN));
        System.out.println("2.5 rounded: " + c.setScale(0, RoundingMode.HALF_EVEN));
        System.out.println("3.5 rounded: " + d.setScale(0, RoundingMode.HALF_EVEN));
    }
}

输出结果:

0.5 rounded: 0
1.5 rounded: 2
2.5 rounded: 2
3.5 rounded: 4

五、BigDecimal和BigInteger底层实现

BigDecimalBigInteger类在Java中提供了对高精度浮点数和大整数的支持。它们的底层实现涉及一些复杂的算法和数据结构。下面我们将分别简要介绍一下这两种类的底层实现和长度限制。

1. BigInteger的底层实现:

BigInteger类的底层实现是基于一个int数组,每个数组元素表示一个“数字单元”(通常是32位),可以理解为一个大整数被分割成若干个较小的部分,这些部分以数组形式存储。在进行大整数运算时,BigInteger会分别对这些较小的部分进行操作,从而实现对大整数的高效处理。

BigInteger的长度限制主要取决于计算机内存。因为它是基于int数组实现的,所以理论上它可以表示非常大的整数。但实际应用中,受限于计算机内存和性能,操作非常大的BigInteger对象可能会导致内存不足或计算速度过慢。

2. BigDecimal的底层实现:

BigDecimal类的底层实现也是基于BigInteger类。BigDecimal对象主要由两部分组成:一个BigInteger对象表示有效数字(即不带小数点的整数部分),一个int类型的值表示小数点位置(即小数点后的位数,也称为精度)。

BigDecimal的长度限制与BigInteger相似,主要受计算机内存和性能的限制。由于它使用了BigInteger作为底层实现,所以它同样可以表示非常大的数值。然而,在实际应用中,处理大量位数的BigDecimal对象可能会导致内存不足或计算速度过慢。因此,在使用BigDecimal时,通常需要根据实际需求设定合适的精度,以确保高效的运算。


六、正则表达式

在Java中,正则表达式(Regular Expression)是一种用于描述字符串模式的强大工具。正则表达式可以用于匹配、查找、替换和验证字符串中的特定字符模式。Java提供了java.util.regex包,其中包含两个主要的类:Pattern和Matcher,用于处理正则表达式。

以下是一个简单的Java正则表达式示例,用于匹配邮箱地址:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexExample {
    public static void main(String[] args) {
        // 定义正则表达式模式
        String regex = "^[\\w._%+-]+@[\\w.-]+\\.[A-Za-z]{2,6}$";
        
        // 将正则表达式编译为Pattern对象
        Pattern pattern = Pattern.compile(regex);
        
        // 定义要测试的字符串
        String email = "example@example.com";
        
        // 创建Matcher对象以检查字符串是否匹配给定的正则表达式
        Matcher matcher = pattern.matcher(email);
        
        // 检查字符串是否匹配正则表达式
        if (matcher.matches()) {
            System.out.println("Email address is valid.");
        } else {
            System.out.println("Email address is not valid.");
        }
    }
}

这个示例中,我们首先定义了一个正则表达式模式,然后使用Pattern.compile()方法将正则表达式编译为Pattern对象。接着,我们创建了一个Matcher对象,将要检查的字符串传递给它,最后使用matcher.matches()方法检查字符串是否匹配正则表达式。如果匹配,我们输出“Email address is valid.”,否则输出“Email address is not valid.”。

正则表达式的作用:

  1. 模式匹配:检查一个字符串是否符合某种特定的模式。
  2. 查找:在字符串中查找满足特定模式的部分。
  3. 替换:根据某种模式将字符串中的一部分替换为另一个字符串。
  4. 字符串拆分:使用特定模式将字符串拆分为子字符串。
  5. 数据验证:验证用户输入是否符合预期格式,例如验证电子邮件地址、电话号码等。

如何学习正则表达式:

  1. 理解基本概念:学习正则表达式的基本组成元素,例如字符、元字符、字符类、量词、分组、选择和锚点等。
  2. 实践练习:通过在线正则表达式练习网站或使用编程语言(如Java、Python等)进行实际练习,以加深理解。
  3. 阅读文档和教程:查阅编程语言的正则表达式文档,了解正则表达式在不同语言中的实现和特性。
  4. 学习常用的正则表达式模式:熟悉常用的正则表达式模式,可以更快地解决实际问题。

常用的正则表达式:

  1. 电子邮件地址:^[\\w._%+-]+@[\\w.-]+\\.[A-Za-z]{2,6}$
  2. URL:^(https?:\\/\\/)?([\\w.-]+\\.)+[\\w-]+(\\/[\\w.,?&%+\\-]*)*$
  3. 电话号码:^\\+?\\d{1,4}?[-.\\s]?\\(?\\d{1,3}?\\)?[-.\\s]?\\d{1,4}[-.\\s]?\\d{1,4}[-.\\s]?\\d{1,9}$
  4. IPv4 地址:^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
  5. 数字:^\\d+$
  6. 日期(yyyy-mm-dd):^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$

这些正则表达式模式可能需要根据实际需求进行调整。学习正则表达式时,请务必结合实际案例进行练习,以提高自己的熟练度。

以下是一些常用的正则表达式规则:

  1. 字符匹配:

    • 普通字符:直接匹配字符本身,例如a匹配字符a
    • 转义字符:使用反斜杠\对特殊字符进行转义,例如\.匹配.字符。
  2. 元字符:

    • .:匹配任意单个字符(除换行符外)。
    • ^:匹配字符串的开头。
    • $:匹配字符串的结尾。
    • *:匹配前面的字符或表达式零次或多次。
    • +:匹配前面的字符或表达式一次或多次。
    • ?:匹配前面的字符或表达式零次或一次。
    • {n}:匹配前面的字符或表达式恰好n次。
    • {n,}:匹配前面的字符或表达式至少n次。
    • {n,m}:匹配前面的字符或表达式至少n次,至多m次。
  3. 字符类:

    • [abc]:匹配方括号内的任意一个字符(abc)。
    • [^abc]:匹配不在方括号内的任意一个字符。
    • [a-z]:匹配指定范围内的任意一个字符。
    • \d:匹配任意数字,等价于[0-9]
    • \D:匹配任意非数字字符,等价于[^0-9]
    • \w:匹配任意单词字符(字母、数字或下划线),等价于[A-Za-z0-9_]
    • \W:匹配任意非单词字符,等价于[^A-Za-z0-9_]
    • \s:匹配任意空白字符(空格、制表符或换行符)。
    • \S:匹配任意非空白字符。
  4. 分组与选择:

    • (expr):捕获括号内的表达式expr,以便以后引用。
    • (?:expr):非捕获括号,匹配括号内的表达式expr,但不捕获结果。
    • expr1|expr2:匹配表达式expr1expr2
  5. 断言:

    • (?=expr):正向肯定预查,在任何匹配expr的字符串开始处匹配查找字符串。
    • (?!expr):正向否定预查,在任何不匹配expr的字符串开始处匹配查找字符串

七、Api和interface

API(Application Programming Interface,应用程序编程接口)和Interface(接口)都是用于描述组件之间如何进行交互的方式,但它们的侧重点和应用场景有所不同。

API:

  1. API是一种更广泛的概念,涉及到一组函数、方法、协议和工具,它们允许开发者访问现有的功能和服务,而无需了解它们的具体实现。
  2. API可以包含多个接口,以及其他相关的资源(例如文档、示例代码和库)。
  3. API可以是为了访问操作系统、数据库、硬件组件或其他软件库的功能而设计的。
  4. API可以跨语言和平台,例如RESTful API可以通过HTTP请求在不同的编程语言和平台之间交互。

Interface:

  1. 接口主要是针对面向对象编程(OOP)中的概念,它定义了一个类或对象需要实现的方法和属性。接口只定义了这些方法和属性的签名,而不包含具体的实现。
  2. 接口通常用于规定一个组件或类的行为,使得其他组件可以与之交互,而不必了解其实现细节。
  3. 接口通常是在同一种编程语言中使用,如Java、C#等。
  4. 接口有助于实现代码解耦,多态和可扩展性。

总之,API是一种更宽泛的概念,可以包含多个接口,它用于描述不同组件之间如何进行交互。而接口主要关注面向对象编程中的一个组件与其他组件之间的契约,用于定义组件之间如何互相沟通。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值