HappyBKs强迫症——BigInteger有多大?

现在什么事都动不动大数据了。连个int也level up成了BigInteger。在一些场景似乎还不得不使用它。

于是有人贱贱地问:“这个天到底有多大呢?”

不,应该是“这个BigInteger到底有多大呢?”

让我们来看看BigInteger的内部结构吧。

在BigInteger中,一个大int其实是由一个int数组实现的,即mag。还有一个int数值signum,用来作为正负标记。

public class BigInteger extends Number implements Comparable<BigInteger> {
    /**
     * The signum of this BigInteger: -1 for negative, 0 for zero, or
     * 1 for positive.  Note that the BigInteger zero <i>must</i> have
     * a signum of 0.  This is necessary to ensures that there is exactly one
     * representation for each BigInteger value.
     *
     * @serial
     */
    final int signum;

    /**
     * The magnitude of this BigInteger, in <i>big-endian</i> order: the
     * zeroth element of this array is the most-significant int of the
     * magnitude.  The magnitude must be "minimal" in that the most-significant
     * int ({@code mag[0]}) must be non-zero.  This is necessary to
     * ensure that there is exactly one representation for each BigInteger
     * value.  Note that this implies that the BigInteger zero has a
     * zero-length mag array.
     */
    final int[] mag;

那么,如何将一个范围大于int范围的数存在BigInteger的mag数组中呢?

BigInteger有很多重载的构造器,我们挑选其中一个来说明就明白了:

    /**
     * Constructs a BigInteger with the specified value, which may not be zero.
     */
    private BigInteger(long val) {
        if (val < 0) {
            val = -val;
            signum = -1;
        } else {
            signum = 1;
        }

        int highWord = (int)(val >>> 32);
        if (highWord==0) {
            mag = new int[1];
            mag[0] = (int)val;
        } else {
            mag = new int[2];
            mag[0] = highWord;
            mag[1] = (int)val;
        }
    }

我们可以看到,对于long长度为8字节,正好是两个int的大小。在上面的构造器中,先通过向右移位32位,取得long的高32位的数,如果为0,则表示long的实际值并没有超过int的范围,于是mag数组只申请一个int的大小,保存long的低32位即可;如果不为0,则说明long的实际值已经超出int的范围,这时候,mag申请两个int大小,将高位32位存在mag[0],低位32位存在mag[1]。

也就是位数高的存在前面,位数低的存在后面。

好吧,回到原先的问题,BigInteger有多大?

mag既然是数组,那么它的长度收到下标范围的影响,即mag的个数不会超过int的最大值,即2的31次方-1,即2147483647。那么每个int是32位。那么mag所能够大表的位数是2147483647*32。

所以,BigInteger的范围应该是[-22147483647*32-1 ,22147483647*32-1 -1]

时间: 2024-10-13 15:29:23

HappyBKs强迫症——BigInteger有多大?的相关文章

BigInteger简析

简介 big-endian和little-endian big-endian.little-endian跟多字节类型的数据有关,比如int,short,long型,而对单字节数据byte却没有影响.big-endian就是低位字节排放在内存的高地址(右边),高位字节排放在内存的低地址(左边).而little-endian正好相反.比如 int a = 0x05060708,在big-endian的情况下存放为:地址     0 1 2 3数据     05 06 07 08在LITTLE-END

【CodeChef】Small factorials(BigInteger笔记)

You are asked to calculate factorials of some small positive integers. Input An integer t, 1<=t<=100, denoting the number of testcases, followed by t lines, each containing a single integer n, 1<=n<=100. Output For each integer n given at inpu

大整数的存储与加减乘除四则运算

当需要计算的整数或计算结果可能会超出long long 所能表示的范围时,应该用大整数来存储和计算(Java里面有BigInteger来存储大整数,这里讨论的是C++语言). 大整数的存储形式是下面这个结构体(包含了构造函数): // 大整数结构体 struct bign{ int d[1000]; int len; bign(){ memset(d, 0, sizeof(d)); len = 0; } }; 首先以字符串的形式读去数据,然后将字符串逐个逆序字符存入d[]数组(可以采用用reve

第十一天20160817

常用类 一.与日期相关的类 1.java.util.Date类:工作中最常用的功能:获得系统当前时间. 2.java.util. Calendar类:抽象类,与日历相关的类.可以获得与日期相关的信息. 3.java.text.DateFormat及其子类:可以对Date与String进行相互的转换. Date date = new Date(); DateFormat df = DateFormat.getDateInstance(); //将Date类型转换为String类型 String s

Java jdk源代码的Math包

jdk源码学习java.math包 阅读JDK源代码java.math中的 java.math.BigDecimal java.math.BigInteger java.math.BitSieve java.math.MathContext java.math.MutableBigInteger java.math.RoundingMode java.math.SignedMutableBigInteger 1.java.math.BigDecimal 不可变的.任意精度的有符号十进制数.Big

java编程入门11 数字处理类

1.数字格式化 1.DecimalFormat类(用于格式化十进制数字) 1)DecimalFormat类是NumberFormat的子类,它可以将一些数字格式化为整数.浮点数.百分数等.通过使用该类可以为要输出的数字加上单位或控制数字的精度.一般情况下可以在实例化DecimalFormat对象时传递数字格式,也可以通过DecimalFormat类中的applyPattern()方法来实现数字的格式化 2)在格式化数字时,DecimalFormat类中使用一些特殊字符构成一个格式化模板,使数字按

java 大数详细讲解

介绍 java中用于操作大叔的类主要有俩种 第一个是BigInteger,代表大整数.第二个是BigDecimal,代表大浮点数.两种类的操作方法类似,所以我们只讲解BigInterger的用法 基本用法 Scanner input = new Scanner(System.in); BigInteger a = input.nextBigInteger(); BigInteger b = input.nextBigInteger(); 1.更改为大数数据类型 String s = "12345

我的全栈之路-Java基础之数据存储

我的全栈之路-Java基础之数据存储 我的全栈之路 2.1 标识符 标识符是在程序开发时给包,类.接口.注解,变量,方法命名的字符序列. 标识符在命名时需要遵守相关的规则和规范: 标识符的命名规则: 标识符不能是Java的关键字和保留字,关键字是Java中被赋予赋予特殊含义的单词,例如public static void等等.保留字是现有Java版本尚未使用,但是未来的Java版本可能会做关键字使用的单词,例如goto,const.但是可以包含关键字,保留字. 标识符可以由字母.数字.下划线组成

Java常用类02

1. 正则表达式 (1) 就是符合一定规则的字符串 (2) 常见规则 A:字符 x 字符 x.举例:'a'表示字符a \\ 反斜线字符. \n 新行(换行)符 ('\u000A') \r 回车符 ('\u000D') B:字符类 [abc] a.b 或 c(简单类) [^abc] 任何字符,除了 a.b 或 c(否定) [a-zA-Z] a到 z 或 A到 Z,两头的字母包括在内(范围) [0-9] 0到9的字符都包括 C:预定义字符类 . 任何字符.我的就是.字符本身,怎么表示呢? \. \d