如何获取最大的BigDecimal值

53

我如何获得 BigDecimal 变量可以容纳的最大可能值?(最好是用编程方式,但硬编码也可以)

编辑
好吧,我刚才意识到这样的东西不存在,因为 BigDecimal 具有任意精度。所以我最终采用了这个值,它足够大:
BigDecimal my = BigDecimal.valueOf(Double.MAX_VALUE)


9
你需要很多内存才能开始。;) - Peter Lawrey
@Peter 这意味着没有这样的常量值,因为BigDecimal是任意精度的,对吗? - Caner
@LAS_VEGAS 正确,这种东西根本不存在。你必须选择一个限制,并说这是你想支持的最大值。 - biziclop
顺便提一下,您可能还想定义允许的最小(正)数字,以限制每个数字存储的位数,从而保持合理的内存占用。 - biziclop
3
BigDecimal能够表示的最大值需要8GB内存。 - Peter Lawrey
5个回答

55

这是一个任意精度类,它可以变得非常大,直到你的计算机的内存耗尽。


51
不正确,它仅限于Integer.MAX_VALUE个单词。 - Andrew
2
安德烈,你能解释一下或者给个链接吗?你说的“它仅限于Integer.MAX_VALUE个单词”是什么意思?谢谢。 - Adelin
34
@Adio,它使用一个int数组来存储数字。在Java中,数组是由int索引的,因此最多可以有Integer.MAX_VALUE个条目。因此,最大可能的BigInteger将消耗大约8GB的RAM(4字节int * 2GB条目)。在64位JVM中,堆大小可能是这个数量的许多倍,所以可用内存并不总是限制最大可能的BigInteger或BigDecimal的因素。 - Simon Kissane
你好。我认为它需要8GB的RAM:2^31-1(Integer.MAX_VALUE)* 4字节(整数大小)= 8589934588字节约等于8GB。 - HF_

14

查看源代码,BigDecimal会将其作为带有基数的BigInteger进行存储。

private BigInteger intVal;
private int scale;

并且来自 BigInteger

/** All integers are stored in 2's-complement form.
63:    * If words == null, the ival is the value of this BigInteger.
64:    * Otherwise, the first ival elements of words make the value
65:    * of this BigInteger, stored in little-endian order, 2's-complement form. */
66:   private transient int ival;
67:   private transient int[] words;

因此,最大的BigDecimal将是:

ival = Integer.MAX_VALUE;
words = new int[Integer.MAX_VALUE]; 
scale = 0;
你可以想办法设置它。:P [编辑] 所以只需计算, 在二进制中是这样的,
(2^35)-2个1(我想是这样?)
用二进制补码表示
01111111111111111...直到你的RAM填满为止。

12

如果内存足够大,则值约为:

2240*10232

(虽然存在一些数量级的误差,但相对而言,这是一个非常精确的估计。)


1
请问您是如何得出那个值的? - Dan
1
我完全不知道,但它肯定始于这个定义:BigDecimal 表示的数字值为 (unscaledValue × 10-scale)。但我认为我使用了一个 byte 后备数组来存储未缩放值的 BigInteger,而不是一个 int,所以我已经“略微”低估了真正的限制。 - biziclop

9

你可以表示 2^2147483647-1,但是超过这个值后一些方法将无法按预期工作。它有646456993位数字。

System.out.println(BigInteger.ONE.shiftLeft(Integer.MAX_VALUE)
                                 .subtract(BigInteger.ONE).bitLength());

打印
2147483647

然而。
System.out.println(BigInteger.ONE.shiftLeft(Integer.MAX_VALUE).bitLength());

打印
-2147483648

由于位数溢出的问题,需要进行翻译。

BigDecimal.MAX_VALUE已经足够大,您不需要检查它。


1
您可以在幅度中存储Integer.MAX_VALUE + 1个整数,因为数组从零开始计数。所有这些整数都有32位,因为它们都是无符号处理的。因此,比特精度为32*2147483648 = 68719476736比特(=8589934592字节=8GiB=8.6GB)。要获得十进制精度,您需要将比特精度乘以log10(2),因此您将获得20686623783个完整的十进制数字,比字符串可以存储的多4倍以上。 现在,您可以使用此数量的数字对10进行幂运算,并减去1以获得最大的BigDecimal值,但不要尝试使用BigDecimal本身进行计算。;) 但现在的问题是...是方法.precision()先出现,其限于Integer.MAX_VALUE,还是我的计算精度先出现?

如果您可以在数组中存储Integer.MAX_VALUE + 1个条目,那么数组的长度将是多少?由于整数属性与数组一起存储,因此它的长度不能超过Integer.MAX_VALUE - geanakuch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接