【问题标题】:BigInteger partitioned into partsBigInteger 分成几部分
【发布时间】:2014-11-20 22:10:38
【问题描述】:

我想访问一个大整数的某些部分。特别是,我想将大整数分成 4 个相等的部分。如果位长不能被 4 整除,我希望添加足够多的前导零以使长度成为 4 的倍数。我有以下代码按描述工作:

public static BigInteger[] partition(BigInteger a) {
    int base = (a.bitLength()+3)/4;

    BigInteger upper = a.shiftRight(2*base);
    BigInteger lower = a.subtract(upper.shiftLeft(2*base));
    BigInteger a2 = lower.shiftRight(base);
    BigInteger a1 = lower.subtract(a2.shiftLeft(base));
    BigInteger a4 = upper.shiftRight(base);
    BigInteger a3 = upper.subtract(a4.shiftLeft(base));
    return new BigInteger[] {a1, a2, a3, a4};
}   

此代码的问题在于创建许多额外的大整数以及许多不必要的移位和减法的开销。也许可以添加一个测试来确保a 至少有 4 位,但在我的情况下这不是必需的,因为在调用函数之前我知道这是正确的。

有没有办法扩展 BigInteger 类并直接使用 int[] mag 数组?扩展类应该有类似于上面给出的partition 的东西,它返回一个由 4 个不可变 BigInteger 值组成的数组。

【问题讨论】:

    标签: java biginteger


    【解决方案1】:

    事实上,我不太明白你的问题。希望我的回答对你有意义:)。

    BigInteger 中,它确实提供了toByteArray(),它返回一个byte[],其中包含BigInteger 本身的2-compliment 表示。同时有一个构造函数采用byte[]

    因此,您的解决方案可以像获取字节数组一样简单,按照您想要的任何肮脏方式对字节数组进行分区,并相应地创建每个结果 BigInteger。这应该可以避免您创建许多不必要的BigIntegers,就像您所关心的那样。

    【讨论】:

    • 你说的问题和我贴的代码一样。字节数组是底层int[] mag 数组的副本,因为该类是不可变的。有没有办法跳过这个额外的复制操作,直接使用底层的int[] mag 数组。
    • 我认为至少它可以像原始代码一样保存几个临时对象。设计为不可变对象,针对结果 BigInteger 的底层int[] 可能不是那么可取。我宁愿在你的算术过程中重用临时的byte[],这进一步节省了临时对象(涉及的临时对象是从原始BigInteger返回的字节数组,以及你用于每个结果BigInteger算术的临时字节数组)
    • 经过长时间的深思熟虑后,我决定我真正需要的是一个可变的大整数类。鉴于标准库的局限性,我同意你的观点,你提出的可能是唯一合理的解决方案。由于边界可能落在一个字节的中间,因此实现并非易事,我可能会发布我的代码。现在,我接受你的回答。谢谢。
    • 恕我直言,非字节边界不是很难解决的问题。我对你的工作最关心的是负数。您是否将对负数进行 2-complient 表示?而且,您的拆分逻辑将导致模棱两可的结果,例如: 1010101 和 1111 将给您相同的结果。这真的是你想要的吗?
    • 不,没有负数。也没有歧义。确实,三个较低分区中的前导零消失了。但这不是问题,因为底座是固定的。它是隐含的,但固定的。
    猜你喜欢
    • 2016-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多