为什么BigInteger不是原始的

Fro*_*gon 8 java primitive biginteger

如果你使用BigInteger(或BigDecimal),并希望对它们执行算术,你必须使用的方法addsubtract,例如.这听起来不错,直到你意识到这一点

 i += d + p + y;
Run Code Online (Sandbox Code Playgroud)

会写成这样的BigInteger:

 i = i.add(d.add(p.add(y)));
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,第一行阅读起来要容易一些.如果Java允许运算符重载但是没有,这可以解决,所以这引出了一个问题:

为什么不是BigInteger原始类型,因此它可以利用与其他原始类型相同的运算符?

Rea*_*tic 16

那是因为BigInteger事实上并不是任何接近原始的东西.它使用数组和一些其他字段实现,各种操作包括复杂操作.例如,以下是执行add:

public BigInteger add(BigInteger val) {
    if (val.signum == 0)
        return this;
    if (signum == 0)
        return val;
    if (val.signum == signum)
        return new BigInteger(add(mag, val.mag), signum);

    int cmp = compareMagnitude(val);
    if (cmp == 0)
        return ZERO;
    int[] resultMag = (cmp > 0 ? subtract(mag, val.mag)
                       : subtract(val.mag, mag));
    resultMag = trustedStripLeadingZeroInts(resultMag);

    return new BigInteger(resultMag, cmp == signum ? 1 : -1);
}
Run Code Online (Sandbox Code Playgroud)

Java中的基元是通常由主机的CPU直接实现的类型.例如,每台现代计算机都有一个用于整数加法的机器语言指令.因此,它在JVM中也可以有非常简单的字节代码.

类似的复杂类型BigInteger通常不能以这种方式处理,也不能转换为简单的字节代码.它不可能是原始的.


所以你的问题可能是"为什么没有运算符在Java中重载".嗯,这是语言哲学的一部分.


为什么不例外,比如String?因为它不仅仅是一个例外的运算符.你需要为运营商的异常*,/,+,-,<<,^等.并且你仍然会在对象本身中进行一些操作(比如powJava中的运算符没有表示),对于基元来说,这些操作是由专业类(如Math)处理的.

  • 虽然需要在各种库中提供支持,但BigInteger作为基本类型仍然是可行的.这样做我没有看到任何技术障碍.即使缺乏CPU支持也不是一个论点:您必须记住早期的​​CPU,其中浮点运算被模拟,同时仍然受到诸如C语言的支持. (3认同)

DSq*_*are 5

从根本上说,因为"原始"的非正式含义是它的数据可以直接用单个CPU指令处理.换句话说,它们是原语,因为它们适合32或64位字,这是CPU使用的数据架构,因此它们可以明确地存储在寄存器中.

因此您的CPU可以进行以下操作:

ADD REGISTER_3 REGISTER_2 REGISTER_1     ;;; REGISTER_3 = REGISTER_1 + REGISTER_2
Run Code Online (Sandbox Code Playgroud)

可以占用任意大量存储器的BigInteger不能存储在单个REGISTER中,并且需要执行多个指令来进行简单求和.

这就是为什么它们不可能是原始类型,现在它们实际上是具有方法和字段的对象,比简单的基元类型复杂得多.

注意:我之所以称之为非正式的原因是因为Java设计人员最终可以将"Java原始类型"定义为他们想要的任何东西,他们拥有这个词,但这是模糊地使用这个词.