Java之大数问题

Posted Huterox

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java之大数问题相关的知识,希望对你有一定的参考价值。

文章目录


Java 这玩意好是好但是相对于Python这类动态语言而言有一个要命的问题,那就是类型带来的一些问题,由于Java 算是一个半静态语言,在声明一个变量的时候会在内存根据类型给你开一个内存。那么这样一来问题就来了,如果我的数贼大就相当容易溢出。有些题目说了可以取余还好办,但是如果没说咋办。那就只能考虑大数问题了。这样一来我们需要考虑的问题就太多了。

不过还好在Java里面其实是有专门处理大数问题的API的。核心的实现原理的话其实和咱们的Python解释器实现Python 1+1 是一样的。
这里咱们扯个闲篇,就是在Python解释器里面实现1+1到底有多难。首先Python是作为一个动态语言,最明显的就是你不需要声明你的变量类型。那你写的时候是爽了,那么解释器怎么知道你的变量是啥类型的,我们都知道Python底层呢是C语言或者Java,当然看你用的是哪个解释器,一般使用的是C解释器,所以本质上,Python代码在运行的时候其实是C语言程序在运行,在推断你的Python代码。

我们都知道Java可以被预编译,所以你idea的代码提示相当棒,但是Python不是,他是动态的,所以你发现你的pycharm的代码提示性其实没有idea好。ok,我们来看看这个解释器先干了啥,首先毫无疑问,由于我是C语言程序在执行代码,所以自然我需要去推断一下你的Python代码里面的变量类型,比如你是int类型的,然后我再用C语言程序给你分配空间,问题来了,对于Python用户而言,他只会去关系我这个里面放的是数字,不会关心咱们的变量到底会不会溢出,事实上在高中的时候我就没想过会有溢出问题,直到我遇到了C语言。 所以C语言解释器还需要去判断一下这个类型的值的长度,一旦太长了,那么必然就需要去使用大数方法去处理。例如他会去申请一个数组去存放,在Java的这个API里面也是的。(如下图)然后你看到了Python程序非常的坚强。所以go python 程序员还是不错的,不过这两货的工程性比较难驾驭。Java虽然啰嗦,但是哪怕你是菜鸟你也能写出还能看的代码,但是Python你试试。所以很多人吐槽Python写个几千行就不行了,其实是因为这个工程量变大了,水平比较低的人很难驾驭好。当然代码提示性较差也是一个问题,不过自从 后面 支持了 这样的语法 a:int 之后,情况稍微缓解了一下,不过工程化还是个问题。

OK,闲话少说,该干点事情了。

处理大数整数

BigInteger

这个是自带的而且很老早的版本就有了,所以不用担心蓝桥杯jdk1.7不能用的情况,不过那个增强for的话好像是1.8后的,这个要注意。
这个BIgInteger的使用其实很简单。我们只要注意几点
就是如何使用 BigInteger 进行运算。因为此时咱们不能直接 + - * / 了。

赋值

这里有两个方法

BigInteger a= new BigInteger("1234567890");
BigInteger b = BigInteger.valueOf("123457890)

加减乘除

a.add(b);
a.subtract(b);
a.multiply(b);
a.divide(b)

求幂函,求公约数

a.pow(2)
a.gcd(b) a,b的最大公约数

当然还有a.abs()

比较判断

comareTo()

compareTo()返回一个int型数据:1 大于; 0 等于; -1 小于;
max(),min():分别返回大的(小的)那个BigInteger数据;

	//比较大小:compareTo(),max(),min()
	@Test
	public void testCompare() 
		BigInteger bigNum1 = new BigInteger("52");
		BigInteger bigNum2 = new BigInteger("27");

		//1.compareTo():返回一个int型数据(1 大于; 0 等于; -1 小于)
		int num = bigNum1.compareTo(bigNum2);			

		//2.max():直接返回大的那个数,类型为BigInteger
		//	等价:return (compareTo(val) > 0 ? this : val);
		BigInteger compareMax = bigNum1.max(bigNum2);	

		//3.min():直接返回小的那个数,类型为BigInteger
		//	等价:return (compareTo(val) < 0 ? this : val);
		BigInteger compareMin = bigNum1.min(bigNum2);	
	

取值


	@Test
	public void testToAnother() 
		BigInteger bigNum = new BigInteger("52");
		int radix = 2;
		
		byte[] num1 = bigNum.toByteArray();
		
		String num2 = bigNum.toString();		
		
		String num3 = bigNum.toString(radix);//转化为2进制
	
		int num4 = bigNum.intValue();

		long num5 = bigNum.longValue();

		float num6 = bigNum.floatValue();
	
		double num7 = bigNum.doubleValue();
	

处理大数浮点数

BigDecimal

大体的操作方法类似。
只是注意几点
就是除法,和注意保留小数的

   public static void main(String[] args)
    
        BigDecimal a = new BigDecimal("4.5635");

        a = a.setScale(3, RoundingMode.HALF_UP);    //保留3位小数,且四舍五入
        System.out.println(a);
    
ROUND_CEILING    //向正无穷方向舍入

ROUND_DOWN    //向零方向舍入

ROUND_FLOOR    //向负无穷方向舍入

ROUND_HALF_DOWN    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5

ROUND_HALF_EVEN    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP,如果是偶数,使用ROUND_HALF_DOWN

ROUND_HALF_UP    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6

ROUND_UNNECESSARY    //计算结果是精确的,不需要舍入模式

ROUND_UP    //向远离0的方向舍入

例题

思路很简单,就是大数问题嘛

package com.huterox.test03;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.math.BigInteger;

public class 复数幂

    public static void main(String[] args) throws FileNotFoundException
    
        PrintWriter out = new PrintWriter(new OutputStreamWriter(new FileOutputStream("复幂数.txt")));
        BigInteger a = BigInteger.valueOf(2);     
        BigInteger b = BigInteger.valueOf(3);  
        BigInteger x = BigInteger.valueOf(2);
        BigInteger y = BigInteger.valueOf(3);
        for(int i=2;i<=123456;++i)    //每次都是两组数据相乘
        
            BigInteger t1 = a.multiply(x); 
            BigInteger t2 = a.multiply(y);  
            BigInteger t3 = b.multiply(x);    
            BigInteger t4 = b.multiply(y);   
            x = t1.subtract(t4);
            y = t2.add(t3);   
            

        
    
        out.println(x.toString()+y.toString()+"i");
        out.close(); 
    


以上是关于Java之大数问题的主要内容,如果未能解决你的问题,请参考以下文章

大数运算之 Java BigInteger 的基本用法

Java之大数相加

Java全栈JavaSE:19.常用类之大数运算日期和日历包装类

Java之大数加减乘除——构建类

java初探秘之推断输入的一串字符是否全为小写字母

Java中的经典算法之冒泡排序(Bubble Sort)