日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java biginteger转int_如何在不使用java.math.BigInteger的情况下使用Java处理非常大的数字...

發(fā)布時間:2025/3/15 java 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java biginteger转int_如何在不使用java.math.BigInteger的情况下使用Java处理非常大的数字... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

我認為程序員應該已經(jīng)實現(xiàn)了自己的bignum庫,因此歡迎在這里。

(當然,稍后您會發(fā)現(xiàn)BigInteger更好,并且可以使用它,但這是寶貴的學習經(jīng)驗。)

(您可以在github上關注本課程的源代碼。此外,我將此內(nèi)容(略有修飾)重新制成了一個由14部分組成的博客系列。)

用Java創(chuàng)建一個簡單的Big number類

那么,我們需要什么?

首先,用數(shù)字表示

基于Java給我們的數(shù)據(jù)類型。

您認為十進制轉(zhuǎn)換是最復雜的部分,讓我們停留在基于十進制的模式下。為了提高效率,我們將不存儲真實的十進制數(shù)字,而是使用base 1 000 000 000 = 10^9 < 2^30。這適合于Java int(最大為2^31或2^32),而兩個這樣的數(shù)字的乘積恰好適合于Java long。

final static int BASE = 1000000000;

final static int BASE_DECIMAL_DIGITS = 9;

然后是數(shù)字數(shù)組:

private int[] digits;

我們是否將數(shù)字存儲在小端或大端中,即較大的部分在前還是后?這并不重要,因此我們決定選擇大端字節(jié),因為這是人類想要閱讀的方式。(目前,我們專注于非負值-稍后我們將為負數(shù)添加一個符號位。)

為了進行測試,我們添加了一個構造函數(shù),該構造函數(shù)允許從此類int []進行初始化。

/**

* creates a DecimalBigInt based on an array of digits.

* @param digits a list of digits, each between 0 (inclusive)

*? ? and {@link BASE} (exclusive).

* @throws IllegalArgumentException if any digit is out of range.

*/

public DecimalBigInt(int... digits) {

for(int digit : digits) {

if(digit < 0 ||? BASE <= digit) {

throw new IllegalArgumentException("digit " + digit +

" out of range!");

}

}

this.digits = digits.clone();

}

另外,此構造函數(shù)還可以用于單個int(如果小于BASE),甚至不可以int(我們將其解釋為0)。因此,我們現(xiàn)在可以執(zhí)行以下操作:

DecimalBigInt d = new DecimalBigInt(7, 5, 2, 12345);

System.out.println(d);

這給了我們de.fencing_game.paul.examples.DecimalBigInt@6af62373,而不是那么有用。因此,我們添加了一個toString()方法:

/**

* A simple string view for debugging purposes.

* (Will be replaced later with a real decimal conversion.)

*/

public String toString() {

return "Big" + Arrays.toString(digits);

}

現(xiàn)在的輸出是Big[7, 5, 2, 12345],這對于測試更有用,不是嗎?

第二,從十進制格式轉(zhuǎn)換。

我們在這里很幸運:我們的基數(shù)(10 ^ 9)是我們要從(10)轉(zhuǎn)換的基數(shù)的冪。因此,我們總是有相同的(9)個十進制數(shù)字代表一個“我們的格式”數(shù)字。(當然,開始時可能少一些數(shù)字。)在下面的代碼中,decimal是一個十進制數(shù)字的字符串。

int decLen = decimal.length();

int bigLen = (decLen-1) / BASE_DECIMAL_DIGITS + 1;

這個奇怪的公式是Java int的編寫方式? bigLen = ceil(decLen/BASE_DECIMAL_DIGITS)。(我希望它是正確的,我們稍后將對其進行測試。)

int firstSome = decLen - (bigLen-1) * BASE_DECIMAL_DIGITS;

這是第一位十進制數(shù)字的長度,應在1到9(含)之間。

我們創(chuàng)建數(shù)組:

int[] digits = new int[bigLen];

循環(huán)瀏覽要創(chuàng)建的數(shù)字:

for(int i = 0; i < bigLen ; i++) {

我們的每個數(shù)字都由原始數(shù)字中的一個數(shù)字塊表示:

String block =

decimal.substring(Math.max(firstSome + (i-1)*BASE_DECIMAL_DIGITS, 0),

firstSome +? ?i? *BASE_DECIMAL_DIGITS);

(Math.max這里是第一個較短的塊在這里需要的。)現(xiàn)在,我們使用常規(guī)的Integer解析函數(shù),并將結(jié)果放入數(shù)組中:

digits[i] = Integer.parseInt(block);

}

從現(xiàn)在創(chuàng)建的數(shù)組中,我們創(chuàng)建DecimalBigInt對象:

return new DecimalBigInt(digits);

讓我們看看這是否有效:

DecimalBigInt d2 = DecimalBigInt.valueOf("12345678901234567890");

System.out.println(d2);

輸出:

Big[12, 345678901, 234567890]

看起來不錯:-)我們也應該用其他一些數(shù)字(長度不同)對其進行測試。

下一部分將是十進制格式,這應該更加容易。

第三,轉(zhuǎn)換為十進制格式。

我們需要將每個數(shù)字輸出為9個十進制數(shù)字。為此,我們可以使用Formatter支持類printf格式字符串的類。

一個簡單的變體是這樣的:

public String toDecimalString() {

Formatter f = new Formatter();

for(int digit : digits) {

f.format("%09d", digit);

}

return f.toString();

}

對于我們的兩個數(shù)字,將返回000000007000000005000000002000012345和000000012345678901234567890。這適用于往返(即,將其饋送到valueOf方法中會得到一個等效的對象),但前導零看起來并不太好看(并且可能與八進制數(shù)產(chǎn)生混淆)。因此,我們需要打破我們美麗的for-each循環(huán),并使用不同的格式字符串作為前兩位。

public String toDecimalString() {

Formatter f = new Formatter();

f.format("%d", digits[0]);

for(int i = 1 ; i < digits.length; i++) {

f.format("%09d", digits[i]);

}

return f.toString();

}

加成。

讓我們從加法開始,因為它很簡單(以后我們可以將其中的一部分用于乘法)。

/**

* calculates the sum of this and that.

*/

public DecimalBigInt plus(DecimalBigInt that) {

...

}

我希望你能喜歡閱讀,你會讀的公式,從而方法名plus,minus,times來代替add,subtract,multiply。

那么,加法是如何工作的?它的工作原理與我們在學校學習到的十進制數(shù)字大于9時相同:加上相應的數(shù)字,如果對于某些數(shù)字,結(jié)果大于10(或BASE在我們的情況下),則將一位帶到下一位數(shù)字。這可能會導致所得數(shù)字比原始數(shù)字多一位。

首先,我們來看一個簡單的例子,即兩個數(shù)字具有相同的數(shù)字位數(shù)。然后看起來就像這樣:

int[] result = new int[this.digits.length];

int carry = 0;

for(int i = this.digits.length-1; i > 0; i--) {

int digSum = carry + this.digits[i] + that.digits[i];

result[i] = digSum % BASE;

carry = digSum / BASE;

}

if(carry > 0) {

int[] temp = new int[result.length + 1];

System.arraycopy(result, 0, temp, 1, result.length);

temp[0] = carry;

result = temp;

}

return new DecimalBigInt(result);

(我們從右到左移動,因此我們可以將任何溢出都帶到下一位數(shù)字。如果我們決定使用Little Endian格式,這會有些漂亮。)

如果兩個數(shù)字的位數(shù)不同,則會變得更加復雜。

為了使其盡可能簡單,我們將其分為幾種方法:

此方法將一位數(shù)字添加到數(shù)組中的元素(可能已經(jīng)包含一些非零值),并將結(jié)果存儲回數(shù)組中。如果有溢出,則通過遞歸調(diào)用將其帶到下一個數(shù)字(索引少一個,而不是一個多)。這樣我們可以確保數(shù)字始終保持在有效范圍內(nèi)。

/**

* adds one digit from the addend to the corresponding digit

* of the result.

* If there is carry, it is recursively added to the next digit

* of the result.

*/

private void addDigit(int[] result, int resultIndex,

int addendDigit)

{

int sum = result[resultIndex] + addendDigit;

result[resultIndex] = sum % BASE;

int carry = sum / BASE;

if(carry > 0) {

addDigit(result, resultIndex - 1, carry);

}

}

下一個對要添加的整個數(shù)字數(shù)組執(zhí)行相同的操作:

/**

* adds all the digits from the addend array to the result array.

*/

private void addDigits(int[] result, int resultIndex,

int... addend)

{

addendIndex = addend.length - 1;

while(addendIndex >= 0) {

addDigit(result, resultIndex,

addend[addendIndex]);

addendIndex--;

resultIndex--;

}

}

現(xiàn)在我們可以實現(xiàn)我們的plus方法:

/**

* calculates the sum of this and that.

*/

public DecimalBigInt plus(DecimalBigInt that) {

int[] result = new int[Math.max(this.digits.length,

that.digits.length)+ 1];

addDigits(result, result.length-1, this.digits);

addDigits(result, result.length-1, that.digits);

// cut of leading zero, if any

if(result[0] == 0) {

result = Arrays.copyOfRange(result, 1, result.length);

}

return new DecimalBigInt(result);

}

如果可以在可能發(fā)生溢出的情況下先查看,然后再創(chuàng)建一個比必要的數(shù)組大的數(shù)組,我們可以在這里做得更好。

啊,一個測試:d2.plus(d2)給出Big[24, 691357802, 469135780],看起來不錯。

乘法。

讓我們記得回到學校時,我們?nèi)绾卧诩埳舷喑烁蟮臄?shù)字?

123 * 123

----------

369? ?<== 123 * 3

246? ? <== 123 * 2

123? ? ?<== 123 * 1

--------

15129

因此,我們必須將第一個數(shù)字的每個數(shù)字[i]與第二個數(shù)字的每個數(shù)字[j]相乘,并將乘積加到結(jié)果的數(shù)字[i + j]中(并注意攜帶)。當然,這里的索引是從右開始而不是從左開始計數(shù)。 (現(xiàn)在,我真的希望我使用低端數(shù)字。)

由于我們兩個數(shù)字的乘積可能超出的范圍int,因此我們使用long乘法。

/**

* multiplies two digits and adds the product to the result array

* at the right digit-position.

*/

private void multiplyDigit(int[] result, int resultIndex,

int firstFactor, int secondFactor) {

long prod = (long)firstFactor * (long)secondFactor;

int prodDigit = (int)(prod % BASE);

int carry = (int)(prod / BASE);

addDigits(result, resultIndex, carry, prodDigit);

}

現(xiàn)在我們可以看到為什么我聲明我的addDigits方法采用resultIndex參數(shù)了。(并且我只是將最后一個參數(shù)更改為varargs參數(shù),以便能夠在此處更好地編寫。)

因此,這里是交叉乘法的方法:

private void multiplyDigits(int[] result, int resultIndex,

int[] leftFactor, int[] rightFactor) {

for(int i = 0; i < leftFactor.length; i++) {

for(int j = 0; j < rightFactor.length; j++) {

multiplyDigit(result, resultIndex - (i + j),

leftFactor[leftFactor.length-i-1],

rightFactor[rightFactor.length-j-1]);

}

}

}

我希望我的索引計算正確。如果使用小尾數(shù)表示法,那就multiplyDigit(result, resultIndex + i + j, leftFactor[i], rightFactor[j])更清楚了,不是嗎?

times現(xiàn)在,我們的方法只需分配結(jié)果數(shù)組,調(diào)用multiplyDigits并包裝結(jié)果。

/**

* returns the product {@code this × that}.

*/

public DecimalBigInt times(DecimalBigInt that) {

int[] result = new int[this.digits.length + that.digits.length];

multiplyDigits(result, result.length-1,

this.digits, that.digits);

// cut off leading zero, if any

if(result[0] == 0) {

result = Arrays.copyOfRange(result, 1, result.length);

}

return new DecimalBigInt(result);

}

對于測試,d2.times(d2)給出Big[152, 415787532, 388367501, 905199875, 19052100],這與我的Emacs calc在此處計算的結(jié)果相同。

比較方式

我們希望能夠比較我們的兩個對象。因此,我們實現(xiàn)了Comparable它的compareTo方法。

public int compareTo(DecimalBigInt that) {

如何知道我們的一個數(shù)字是否大于另一個?首先,我們比較數(shù)組的長度。由于我們注意不要引入任何前導零(是嗎?),因此較長的數(shù)組應具有較大的數(shù)字。

if(this.digits.length < that.digits.length) {

return -1;

}

if (that.digits.length < this.digits.length) {

return 1;

}

如果長度相同,我們可以按元素進行比較。由于我們使用big endian(即big end首先出現(xiàn)),因此我們從頭開始。

for(int i = 0; i < this.digits.length; i++) {

if(this.digits[i] < that.digits[i]) {

return -1;

}

if(that.digits[i] < this.digits[i]) {

return 1;

}

}

如果一切都相同,那么顯然我們的數(shù)字是相同的,我們可以返回0。

return 0;

}

equals + hashCode()

每一個良好的不可變類應該實現(xiàn)equals()和hashCode()在合適(兼容)的方式。

對于我們的hashCode(),我們只需對數(shù)字進行求和,然后將它們乘以小質(zhì)數(shù),以確保數(shù)字切換不會產(chǎn)生相同的哈希碼:

/**

* calculates a hashCode for this object.

*/

public int hashCode() {

int hash = 0;

for(int digit : digits) {

hash = hash * 13 + digit;

}

return hash;

}

在該equals()方法中,我們可以簡單地委托給compareTo方法,而不必再次實現(xiàn)相同的算法:

/**

* compares this object with another object for equality.

* A DecimalBigInt is equal to another object only if this other

* object is also a DecimalBigInt and both represent the same

* natural number.

*/

public boolean equals(Object o) {

return o instanceof DecimalBigInt &&

this.compareTo((DecimalBigInt)o) == 0;

}

所以,今天足夠了。減法(可能是負數(shù))和除法更加復雜,因此我暫時將其省略。要計算90的階乘,就足夠了。

計算大階乘:

這里的階乘函數(shù):

/**

* calculates the factorial of an int number.

* This uses a simple iterative loop.

*/

public static DecimalBigInt factorial(int n) {

DecimalBigInt fac = new DecimalBigInt(1);

for(int i = 2; i <= n; i++) {

fac = fac.times(new DecimalBigInt(i));

}

return fac;

}

這給了我們

fac(90) = 1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000

從任意基數(shù)表示形式轉(zhuǎn)換

在下一個frodosamoa問題的提示下,我寫了關于如何從任意(位置)數(shù)字系統(tǒng)轉(zhuǎn)換為我們(或想要)進行計算的答案。(在該示例中,我從三進制轉(zhuǎn)換為十進制,而問題是從十進制轉(zhuǎn)換為二進制。)

在這里,我們想從任意數(shù)字系統(tǒng)(好的,基數(shù)在2到36之間,所以我們可以用來將一位數(shù)字Character.digit()轉(zhuǎn)換為整數(shù))轉(zhuǎn)換為帶有基數(shù)BASE(= 1.000.000.000,但這在這里并不重要) 。

基本上,我們使用Horner方案來計算多項式的值,該數(shù)字在基數(shù)給定的點處作為系數(shù)。

sum[i=0..n] digit[i] * radix^i

可以使用以下循環(huán)計算:

value = 0;

for? i = n .. 0

value = value * radix + digit[i]

return value

由于我們的輸入字符串是big-endian,因此我們不必倒數(shù),而是可以使用簡單的增強型for循環(huán)。(在Java中看起來更難看,因為我們沒有運算符重載,也沒有從int到DecimalBigInt類型的自動裝箱。)

public static DecimalBigInt valueOf(String text, int radix) {

DecimalBigInt bigRadix = new DecimalBigInt(radix);

DecimalBigInt value = new DecimalBigInt(); // 0

for(char digit : text.toCharArray()) {

DecimalBigInt bigDigit =

new DecimalBigInt(Character.digit(digit, radix));

value = value.times(bigRadix).plus(bigDigit);

}

return value;

}

在我的實際實現(xiàn)中,我添加了一些錯誤檢查(和引發(fā)異常),以確保我們確實有一個有效的數(shù)字,當然還有文檔注釋。

轉(zhuǎn)換為任意位置系統(tǒng)更為復雜,因為它涉及余數(shù)和除法(按任意基數(shù)),而我們尚未實現(xiàn),因此目前還沒有實現(xiàn)。當我對分割方法有個好主意時,它將完成。(在這里我們只需要用小數(shù)(一位數(shù)字)進行除法,這可能比一般的除法更容易。)

小數(shù)除法

在學校里,我學會了長除法。這是一個小(一位數(shù)字)除數(shù)的示例,我們在德國使用的表示法(帶有關于背景計算的注釋,我們通常不會寫),以十進制表示:

12345 : 6 = 02057? ? ?1 / 6 =? 0

-0┊┊┊┊? ? ? ? ? ? ? ? ?0 * 6 =? 0

──┊┊┊┊

12┊┊┊? ? ? ? ? ? ? ? 12 / 6 =? 2

-12┊┊┊? ? ? ? ? ? ? ? ?2 * 6 = 12

──┊┊┊

03┊┊? ? ? ? ? ? ? ? ?3 / 6 =? 0

- 0┊┊? ? ? ? ? ? ? ? ?0 * 6 =? 0

──┊┊

34┊? ? ? ? ? ? ? ? 34 / 6 =? 5

-30┊? ? ? ? ? ? ? ? ?5 * 6 = 30

──┊

45? ? ? ? ? ? ? ? 45 / 6 =? 7

-42? ? ? ? ? ? ? ? ?7 * 6 = 42

──

3? ? ?==> quotient 2057, remainder 3.

當然,如果我們有本征余數(shù)運算,則不需要計算這些乘積(0、12、0、30、42)并減去它們。然后看起來像這樣(當然,我們這里不需要編寫操作):

12345 : 6 = 02057? ? ?1 / 6 =? 0,? ?1 % 6 = 1

12┊┊┊? ? ? ? ? ? ? ? 12 / 6 =? 2,? 12 % 6 = 0

03┊┊? ? ? ? ? ? ? ? ?3 / 6 =? 0,? ?3 % 6 = 3

34┊? ? ? ? ? ? ? ? 34 / 6 =? 5,? 34 % 6 = 4

45? ? ? ? ? ? ? ? 45 / 6 =? 7,? 45 % 6 = 3

3

==> quotient 2057, remainder 3.

如果我們用另一種格式編寫的話,這看起來已經(jīng)很像短除法了。

我們可以觀察(并證明)以下內(nèi)容:

如果我們有一個兩位數(shù)的數(shù)字x,其第一位數(shù)字小于我們的除數(shù)d,x / d則它是一位數(shù),并且x % d也是一位數(shù)字,小于d。這與歸納一起表明,我們只需要用除數(shù)除以兩位數(shù)(余數(shù))即可。

回到以BASE為基數(shù)的大數(shù)字:所有兩位數(shù)字都可以用Java表示long,那里有native /和%。

/**

* does one step in the short division algorithm, i.e. divides

*? a two-digit number by a one-digit one.

*

* @param result the array to put the quotient digit in.

* @param resultIndex the index in the result array where

*? ? ? ? ? ? ?the quotient digit should be put.

* @param divident the last digit of the divident.

* @param lastRemainder the first digit of the divident (being the

*? ? ? ? ? ?remainder of the operation one digit to the left).

*? ? ? ? ? ?This must be < divisor.

* @param divisor the divisor.

* @returns the remainder of the division operation.

*/

private int divideDigit(int[] result, int resultIndex,

int divident, int lastRemainder,

int divisor) {

assert divisor < BASE;

assert lastRemainder < divisor;

long ent = divident + (long)BASE * lastRemainder;

long quot = ent / divisor;

long rem = ent % divisor;

assert quot < BASE;

assert rem < divisor;

result[resultIndex] = (int)quot;

return (int)rem;

}

現(xiàn)在,我們將循環(huán)調(diào)用此方法,始終將前一次調(diào)用的結(jié)果反饋為lastRemainder。

/**

* The short division algorithm, like described in

* Wikipedia's

*? ?article Short division.

* @param result an array where we should put the quotient digits in.

* @param resultIndex the index in the array where the highest order digit

*? ? ?should be put, the next digits will follow.

* @param divident the array with the divident's digits. (These will only

*? ? ? ? ? be read, not written to.)

* @param dividentIndex the index in the divident array where we should

*? ? ? ? ?start dividing. We will continue until the end of the array.

* @param divisor the divisor. This must be a number smaller than

*? ? ? ? {@link #BASE}.

* @return the remainder, which will be a number smaller than

*? ? ?{@code divisor}.

*/

private int divideDigits(int[] result, int resultIndex,

int[] divident, int dividentIndex,

int divisor) {

int remainder = 0;

for(; dividentIndex < divident.length; dividentIndex++, resultIndex++) {

remainder = divideDigit(result, resultIndex,

divident[dividentIndex],

remainder, divisor);

}

return remainder;

}

此方法仍返回一個int,其余為。

現(xiàn)在我們要有一個返回DecimalBigInt的公共方法,所以我們創(chuàng)建一個。它的任務是檢查參數(shù),為工作方法創(chuàng)建一個數(shù)組,丟棄其余部分并從結(jié)果中創(chuàng)建DecimalBigInt。(構造函數(shù)刪除可能存在的前導零。)

/**

* Divides this number by a small number.

* @param divisor an integer with {@code 0 < divisor < BASE}.

* @return the integer part of the quotient, ignoring the remainder.

* @throws IllegalArgumentException if the divisor is <= 0 or >= BASE.

*/

public DecimalBigInt divideBy(int divisor)

{

if(divisor <= 0 || BASE <= divisor) {

throw new IllegalArgumentException("divisor " + divisor +

" out of range!");

}

int[] result = new int[digits.length];

divideDigits(result, 0,

digits, 0,

divisor);

return new DecimalBigInt(result);

}

我們還有一個類似的方法,它返回余數(shù):

/**

* Divides this number by a small number, returning the remainder.

* @param divisor an integer with {@code 0 < divisor < BASE}.

* @return the remainder from the division {@code this / divisor}.

* @throws IllegalArgumentException if the divisor is <= 0 or >= BASE.

*/

public int modulo(int divisor) {

if(divisor <= 0 || BASE <= divisor) {

throw new IllegalArgumentException("divisor " + divisor +

" out of range!");

}

int[] result = new int[digits.length];

return divideDigits(result, 0,

digits, 0,

divisor);

}

這些方法可以這樣調(diào)用:

DecimalBigInt d3_by_100 = d3.divideBy(100);

System.out.println("d3/100 = " + d3_by_100);

System.out.println("d3%100 = " + d3.modulo(100));

轉(zhuǎn)換為任意基數(shù)

現(xiàn)在我們有了轉(zhuǎn)換為任意基數(shù)的基礎。當然,不是真正任意的,只有基數(shù)小于BASE允許的基數(shù),但這應該不是太大的問題。

正如在有關轉(zhuǎn)換數(shù)字的另一個答案中已經(jīng)回答的那樣,我們必須執(zhí)行“除法,余數(shù),乘法,加法”。“乘加”部分實際上只是將各個數(shù)字放在一起,因此我們可以用一個簡單的數(shù)組代替它-訪問。

由于我們總是需要商和余數(shù),因此我們將不使用public方法modulo和divideBy,而是反復調(diào)用該divideDigits方法。

/**

* converts this number to an arbitrary radix.

* @param radix the target radix, {@code 1 < radix < BASE}.

* @return the digits of this number in the base-radix system,

*? ? ?in big-endian order.

*/

public int[] convertTo(int radix)

{

if(radix <= 1 || BASE <= radix) {

throw new IllegalArgumentException("radix " + radix +

" out of range!");

}

首先,對0進行特殊處理。

// zero has no digits.

if(digits.length == 0)

return new int[0];

然后,我們?yōu)榻Y(jié)果數(shù)字(足夠長)和一些其他變量創(chuàng)建一個數(shù)組。

// raw estimation how many output digits we will need.

// This is just enough in cases like BASE-1, and up to

// 30 digits (for base 2) too much for something like (1,0,0).

int len = (int) (Math.log(BASE) / Math.log(radix) * digits.length)+1;

int[] rDigits = new int[len];

int rIndex = len-1;

int[] current = digits;

int quotLen = digits.length;

quotLen是最后一個商的位數(shù)(不包括前導零)。如果為0,則完成。

while(quotLen > 0)? {

下一個商的新數(shù)組。

int[] quot = new int[quotLen];

商與余數(shù)運算。商現(xiàn)在在quot,余數(shù)在rem。

int rem = divideDigits(quot, 0,

current, current.length - quotLen,

radix);

我們將其余部分放在輸出數(shù)組中(從最后一位開始填充)。

rDigits[rIndex] = rem;

rIndex --;

然后我們將數(shù)組交換到下一輪。

current = quot;

如果商中有前導零(由于基數(shù)小于BASE,最大為1),我們將商大小縮小1。下一個數(shù)組將更小。

if(current[0] == 0) {

// omit leading zeros in next round.

quotLen--;

}

}

循環(huán)之后,rDigits數(shù)組中可能有前導零,我們將其切除。

// cut of leading zeros in rDigits:

while(rIndex < 0 || rDigits[rIndex] == 0) {

rIndex++;

}

return Arrays.copyOfRange(rDigits, rIndex, rDigits.length);

}

而已。但是,它看起來有點復雜。這是一個如何使用它的示例:

System.out.println("d4 in base 11: " +

Arrays.toString(d4.convertTo(11)));

System.out.println("d5 in base 7: " +

Arrays.toString(d5.convertTo(7)));

它們打印[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0]和[1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0],與我們之前解析的數(shù)字相同(不過是從字符串中提取的)。

基于此,我們還可以將其格式化為字符串:

/**

* Converts the number to a String in a given radix.

* This uses {@link Character.digit} to convert each digit

* to one character.

* @param radix the radix to use, between {@link Character.MIN_RADIX}

*? ?and {@link Character.MAX_RADIX}.

* @return a String containing the digits of this number in the

*? ?specified radix, using '0' .. '9' and 'a' .. 'z' (as much as needed).

*/

public String toString(int radix) {

if(radix < Character.MIN_RADIX || Character.MAX_RADIX < radix) {

throw new IllegalArgumentException("radix out of range: " + radix);

}

if(digits.length == 0)

return "0";

int[] rdigits = convertTo(radix);

StringBuilder b = new StringBuilder(rdigits.length);

for(int dig : rdigits) {

b.append(Character.forDigit(dig, radix));

}

return b.toString();

}

總結(jié)

以上是生活随笔為你收集整理的java biginteger转int_如何在不使用java.math.BigInteger的情况下使用Java处理非常大的数字...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。