How to handle very large numbers in Java without using java.math.BigInteger

How will I do arithmetic, + - / *% !, with arbitrarily large integers without using java.math.BigInteger ?

For example, factorial 90 returns 0 in Java. I would like to be able to solve this problem.

+57
java math integer biginteger
Mar 15 2018-11-11T00:
source share
7 answers

I think that a programmer had to implement his own bigmoon library once, so I welcome you here.

(Of course, you will later find that BigInteger is better, and use this, but it is a valuable learning experience.)

(You can follow the source code for this course on github . Also, I redid this (slightly polished) into a 14-section blog series .)

Creating a simple class of large numbers in Java

So what do we need?

First, the representation of a number,

based on the data types that Java gives us.

Do you think decimal conversion is the hardest part, let's stay in decimal mode. For efficiency, we will not store real decimal digits, but work in the database 1 000 000 000 = 10^9 < 2^30 . This corresponds to a Java int (up to 2^31 or 2^32 ), and the product of two such digits fits perfectly into Java long .

 final static int BASE = 1000000000; final static int BASE_DECIMAL_DIGITS = 9; 

Then a set of numbers:

 private int[] digits; 

Do we save the numbers at the small or large end, i.e. larger parts first or last time? It doesn't really matter, so we make a decision about how people want to read it. (At the moment, we focus on non-negative values ​​- later we will add a signed bit for negative numbers.)

For testing purposes, we add a constructor that allows us to initialize such an 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(); } 

As an added bonus, this constructor can also be used for a single int (if less than BASE ) and even for no int (which we will interpret as 0). So now we can do this:

 DecimalBigInt d = new DecimalBigInt(7, 5, 2, 12345); System.out.println(d); 

This gives us de.fencing_game.paul.examples.DecimalBigInt@6af62373 , which is not so useful. So, we add the toString() method:

 /** * A simple string view for debugging purposes. * (Will be replaced later with a real decimal conversion.) */ public String toString() { return "Big" + Arrays.toString(digits); } 

Now the result is Big[7, 5, 2, 12345] , which is more useful for testing, isn't it?

Secondly, conversion from decimal format.

We were lucky: our base (10 ^ 9) is the strength of the base that we want to convert from (10). Thus, we always have the same number (9) of decimal digits representing the β€œour format” digit. (Of course, there may be fewer digits at the beginning.) In the following code, decimal is a string of decimal digits.

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

This weird formula is the Java way of writing bigLen = ceil(decLen/BASE_DECIMAL_DIGITS) . (I hope this is correct, we will check it later.)

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

This is the length of the first block of decimal digits, must be between 1 and 9 (inclusive).

We create our array:

  int[] digits = new int[bigLen]; 

Quoting through the numbers you need to create:

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

Each of our numbers is represented by a block of numbers in the original number:

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

( Math.max needed here for the first shorter block.) Now we use the usual function for parsing integers and put the result in an array:

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

From the created array, we create our DecimalBigInt object:

 return new DecimalBigInt(digits); 

Let's see if this works:

 DecimalBigInt d2 = DecimalBigInt.valueOf("12345678901234567890"); System.out.println(d2); 

Output:

 Big[12, 345678901, 234567890] 

It looks right :-) We need to check it with some other numbers (of different lengths) too.

The next part will be decimal formatting, this should be even simpler.

Thirdly, conversion to decimal format.

We need to output our individual digits as 9 decimal digits each. For this, we can use the Formatter class, which supports printf format strings.

A simple option would be the following:

 public String toDecimalString() { Formatter f = new Formatter(); for(int digit : digits) { f.format("%09d", digit); } return f.toString(); } 

This returns 000000007000000005000000002000012345 and 000000012345678901234567890 for our two numbers. This works for round-trip (i.e., passing it to the valueOf method gives an equivalent object), but leading zeros are not very nice to look at (and can create confusion with octal numbers). Therefore, we need to break our beautiful for each cycle and use a different format string for the first and next digits.

 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(); } 

Addition.

We'll start by adding, because it's simple (and we can use parts of it for later multiplication).

 /** * calculates the sum of this and that. */ public DecimalBigInt plus(DecimalBigInt that) { ... } 

I need method names that you can read as if you were reading a formula, so plus , minus , times instead of add , subtract , multiply .

So how does the add-on work? It works in the same way as we learned it at school, for decimal numbers exceeding 9: add the corresponding numbers, and if for some time the result is more than 10 (or BASE in our case), transfer it to the next digit, This can lead to the fact that the resulting number will have one digit more than the original.

First we look at the simple case where both numbers have the same number of digits. Then it just looks like this:

 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); 

(We go from right to left, so we can transfer any overflows to the next digit. It would be a bit prettier if we decided to use the Little Endian format.)

If both numbers do not have the same number of digits, this is a little complicated.

To make this as simple as possible, we will divide it into several methods:

This method adds one digit to the array element (which may already contain some non-zero value) and stores the result in the array. If there was an overflow, we transfer it to the next digit (which has an index one less than one) using a recursive call. Thus, we guarantee that our numbers will always be in the acceptable range.

 /** * 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); } } 

The following does the same for a whole array of numbers:

 /** * 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--; } } 

Now we can implement our plus method:

 /** * 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); } 

We could do a little better if we looked earlier, if overflow is even possible, and only then create an array that is larger than necessary.

Ah, one test: d2.plus(d2) gives Big[24, 691357802, 469135780] that looks right.

Multiplication.

Think back to school, how did we multiply large numbers on paper?

 123 * 123 ---------- 369 <== 123 * 3 246 <== 123 * 2 123 <== 123 * 1 -------- 15129 

So, we must multiply each digit [i] of the first number by each digit [j] of the second number and add the product to the figure [i + j] of the result (and pay attention to the carry). Of course, here the indices are calculated on the right, and not on the left. (Now I'm really sorry that I did not use low-valued numbers.)

Since the product of our two digits may go beyond the int range, we use long to multiply.

 /** * 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); } 

Now we can understand why I announced that my addDigits method accepts the resultIndex parameter. (And I just changed the last argument to the varargs parameter so that it would be better to write this here.)

So here is the cross-multiplication method:

 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]); } } } 

Hope I have index calculations. With a little endian view, that would be multiplyDigit(result, resultIndex + i + j, leftFactor[i], rightFactor[j]) - pretty clear, right?

Our times method now only needs to allocate an array of results, call multiplyDigits and wrap the result.

 /** * 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); } 

For testing, d2.times(d2) gives Big[152, 415787532, 388367501, 905199875, 19052100] , which is the same as my Emacs calc calculates.

Comparison

We want to be able to compare our two objects. So, we implement Comparable<DecimalBigInt> and the compareTo method.

 public int compareTo(DecimalBigInt that) { 

How to find out if one of our numbers is larger? First, we compare the length of the arrays. Since we took care not to lead to any leading zeros (we?), A longer array should have a larger number.

  if(this.digits.length < that.digits.length) { return -1; } if (that.digits.length < this.digits.length) { return 1; } 

If the length is the same, we can compare the item. Since we use a large endian (that is, a large end in the first place), we start from the very beginning.

  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; } } 

If everything was the same, it is obvious that our numbers are identical, and we can return 0 .

  return 0; } 

equals + hashCode()

Every good immutable class should implement equals() and hashCode() appropriate (and compatible) way.

For our hashCode() we simply sum the digits, multiplying them by a small downtime, to make sure that switching the digits does not result in the same hash code:

 /** * calculates a hashCode for this object. */ public int hashCode() { int hash = 0; for(int digit : digits) { hash = hash * 13 + digit; } return hash; } 

In the equals() method, we can simply delegate the compareTo method, rather than repeating the same algorithm:

 /** * 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; } 



So that's enough for today. Subtraction (and maybe negative numbers) and division are more complicated, so now I omit them. To calculate factorial 90, this should be enough.

Calculation of large factorials:

Here's the factorial function:

 /** * 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; } 

It gives us

 fac(90) = 1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000 

Convert from arbitrary radial representations

In response to the following question frodosamoa, I wrote my answer on how to convert from arbitrary (positional) systems with numbers to one in which we can (or want) to calculate . (In the example there, I converted from three-dimensional to decimal, while the question was about the decimal value for binary.)

Here we want to convert from an arbitrary system of numbers (well, with a radius between 2 and 36, so we can use Character.digit() to convert individual digits to ints) into our system using radix BASE (= 1.000.000.000, but here it is not very important).

We mainly use the Horner scheme to calculate the value of a polynomial with numbers as coefficients at the point given by the base.

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

can be calculated using this loop:

 value = 0; for i = n .. 0 value = value * radix + digit[i] return value 

Since our input lines are large, we do not need to pay attention, but they can use a simple extended loop. (This looks more ugly in Java, since we have no operator overloading, and no autoboxing from int to our DecimalBigInt type.)

 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; } 

In my actual implementation, I added some error checking (and throwing exception) to make sure that we really have a real number, and, of course, a comment on the documentation.




Transformation in an arbitrary positional system is more complicated, because it includes the remainder and division (into arbitrary radix), which we have not yet implemented - so for now. This will be done when I have a good idea on how to make the separation. (We only need division by small (single-digit) numbers, which can be simpler than general division.)

Small numbers

At school, I learned a long division . Here is an example of a small (one-bit) divisor in the notation that we use here in Germany (with annotations about background calculations that we usually won't write) in the decimal system:

  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. 

We should not calculate these products (0, 12, 0, 30, 42) and subtract them if we have a native remainder operation. Then it looks (of course, we will not need to write operations here):

  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. 

It already looks like a short split if we write it in a different format.

We can observe (and prove) the following:

If we have a two-digit number x with the first digit less than our divisor d, than x / d is a one-digit number, and x % d also a one-digit number less than d. This, together with induction, shows that we need to ever divide (with the remainder) two-digit numbers by our divisor.

Returning to our large numbers with a BASE base: all two-digit numbers are represented as Java long , and there we have native / and % .

 /** * does one step in the short division algorithm, ie 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; } 

Now we will call this method in a loop, always feeding the result from the previous callback as lastRemainder .

 /** * The short division algorithm, like described in * <a href="http://en.wikipedia.org/wiki/Short_division">Wikipedia's * article <em>Short division</em></a>. * @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 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; } 

This method still returns int, the remainder.

Now we want the public method to return DecimalBigInt, so we create it. He has the task of checking the arguments, creating an array for the working method, discarding the remainder, and creating DecimalBigInt from the result. (The constructor removes the leading zero, which may be there.)

 /** * 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); } 

We also have a similar method that returns the remainder instead:

 /** * 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); } 

These methods can be called as follows:

  DecimalBigInt d3_by_100 = d3.divideBy(100); System.out.println("d3/100 = " + d3_by_100); System.out.println("d3%100 = " + d3.modulo(100)); 

Convert to arbitrary radius

Now we have the basics for converting to an arbitrary radius. Of course, not very arbitrary, only radions smaller than BASE permissible, but this should not be too big a problem.

As already mentioned in another answer on the conversion of numbers, we must do "division, remainder, multiply, add." The multiply-add part is actually only single digits, so we can replace it with simple access to the array.

Since we always need both the private and the rest, we will not use the public modulo and divideBy , but instead call the divideDigits method 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!"); } 

First, handling a special case for 0.

  // zero has no digits. if(digits.length == 0) return new int[0]; 

Then we create an array for the digits of the result (long enough), and some other variables.

  // 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 is the number of digits (excluding leading zeros) in the last quotient. If it is 0, we are done.

  while(quotLen > 0) { 

A new array for the next private.

  int[] quot = new int[quotLen]; 

Operation quotient-and-else. The factor is now in quot , the remainder in rem .

  int rem = divideDigits(quot, 0, current, current.length - quotLen, radix); 

We put the remainder in the output array (filling it with the last digit).

  rDigits[rIndex] = rem; rIndex --; 

Then we replace the arrays for the next round.

  current = quot; 

If the factor has leading zeros (there will be no more than one, since radix is ​​less than BASE), we reduce the size of the factor by one. The next array will be smaller.

  if(current[0] == 0) { // omit leading zeros in next round. quotLen--; } } 

rDigits , .

  // cut of leading zeros in rDigits: while(rIndex < 0 || rDigits[rIndex] == 0) { rIndex++; } return Arrays.copyOfRange(rDigits, rIndex, rDigits.length); } 

What is it. . , :

  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] , , ( String).

:

 /** * 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(); } 
+238
15 . 2018-11-11T00:
source share

, - , BigInteger . 90 BigInteger , , :

 public static BigInteger factorial(BigInteger value) { BigInteger total = BigInteger.ONE; for (int i = 0; value.compareTo(BigInteger.ONE) == 1; i++) { total = total.multiply(value); value = value.subtract(BigInteger.ONE); } return total; } 
+2
15 . 2018-11-11T00:
source share

Java + , - , * , / % Java .

, , , double long , " ", ​​ Java ( BigDecimal , BigInteger ), , . , , Java .

+1
15 . '11 21:24
source share

: -

 public class BigNumberMultiplication { private static int[] firstBigNumber = null; private static int[] secondBigNumber = null; public static int[] baseMul(int[] baseMultiple, int base) { System.out.println("baseMultiple" + Arrays.toString(baseMultiple) + base); for (int i = 0; i < baseMultiple.length; i++) { baseMultiple[i] *= base; } System.out.println("basemultipleresultwithoutcarryforward" + baseMultiple); return carryForward(baseMultiple); } public static int[] basePowerMul(int[] basePowerMultiple, int base, int power) { int basePowerMultipleTemp[] = baseMul(basePowerMultiple, base); System.out.println("basePowerMultipleTemp" + Arrays.toString(basePowerMultipleTemp) + "power" + power); int basePowerMultipleResult[] = new int[basePowerMultipleTemp.length + (power - 1)]; for(int i = 0; i < basePowerMultipleTemp.length; i++) basePowerMultipleResult[i] = basePowerMultipleTemp[i]; if(power > 1){ for(int i = 0; i < (power - 1); i++) basePowerMultipleResult[basePowerMultipleTemp.length + i] = 0; } System.out.println("basepowermulresult" + Arrays.toString(basePowerMultipleResult)); return basePowerMultipleResult; } public static int[] addBigNumber(int[] finalNumberInArray, int[] finalNumberInArrayTemp){ System.out.println("final number in array" + Arrays.toString(finalNumberInArray) + "finalNumberInTemp" + Arrays.toString(finalNumberInArrayTemp)); int n = finalNumberInArray.length; for(int i = (finalNumberInArrayTemp.length - 1); i >= 0; i--){ finalNumberInArray[n - 1] += finalNumberInArrayTemp[i]; n--; } return carryForward(finalNumberInArray); } public static int[] carryForward(int[] arrayWithoutCarryForward){ int[] arrayWithCarryForward = null; System.out.println("array without carry forward" + Arrays.toString(arrayWithoutCarryForward)); for (int i = arrayWithoutCarryForward.length - 1; i > 0; i--) { if (arrayWithoutCarryForward[i] >= 10) { int firstDigit = arrayWithoutCarryForward[i] % 10; int secondDigit = arrayWithoutCarryForward[i] / 10; arrayWithoutCarryForward[i] = firstDigit; arrayWithoutCarryForward[i - 1] += secondDigit; } } if(arrayWithoutCarryForward[0] >= 10){ arrayWithCarryForward = new int[arrayWithoutCarryForward.length + 1]; arrayWithCarryForward[0] = arrayWithoutCarryForward[0] / 10; arrayWithCarryForward[1] = arrayWithoutCarryForward[0] % 10; for(int i = 1; i < arrayWithoutCarryForward.length; i++) arrayWithCarryForward[i + 1] = arrayWithoutCarryForward[i]; } else{ arrayWithCarryForward = arrayWithoutCarryForward; } System.out.println("array with carry forward" + Arrays.toString(arrayWithCarryForward)); return arrayWithCarryForward; } public static int[] twoMuscularNumberMul(){ int finalNumberInArray[] = null; for(int i = 0; i < secondBigNumber.length; i++){ if(secondBigNumber[i] == 0){} else { int[] finalNumberInArrayTemp = basePowerMul(Arrays.copyOf(firstBigNumber, firstBigNumber.length), secondBigNumber[i], secondBigNumber.length - i); if(finalNumberInArray == null){ finalNumberInArray = finalNumberInArrayTemp; System.out.println("finalNumberInArray" + Arrays.toString(finalNumberInArray)); } else{ finalNumberInArray = addBigNumber(finalNumberInArray, finalNumberInArrayTemp); System.out.println("finalNumberInArray" + Arrays.toString(finalNumberInArray)); } } } return finalNumberInArray; } public static int [] readNumsFromCommandLine() { Scanner s = new Scanner(System.in); System.out.println("Please enter the number of digit"); int count = s.nextInt(); System.out.println("please enter the nuumber separated by space"); s.nextLine(); int [] numbers = new int[count]; Scanner numScanner = new Scanner(s.nextLine()); for (int i = 0; i < count; i++) { if (numScanner.hasNextInt()) { numbers[i] = numScanner.nextInt(); } else { System.out.println("You didn't provide enough numbers"); break; } } return numbers; } public static void main(String[] args) { firstBigNumber = readNumsFromCommandLine(); secondBigNumber = readNumsFromCommandLine(); System.out.println("1st number" + Arrays.toString(firstBigNumber) + "2nd number" + Arrays.toString(secondBigNumber)); int[] finalArray = twoMuscularNumberMul(); System.out.println(Arrays.toString(finalArray)); } } 
+1
04 . '13 5:12
source share

BigInteger {

  public static String checkSignWithRelational(int bigInt1, int bigInt2){ if( bigInt1 < 0){ return "negative"; }else { return "positive"; } } BigInteger( long init) { Long.parseLong(bigInt1); } BigInteger String (String init){ return null; } private static int intLenght(int bigInt) { return Integer.toString(bigInt).length(); } private static int[] intToArray(int bigInt, int bigIntLength, int arrayLength) { int array[] = new int[arrayLength ]; for (int i = 0; i < arrayLength ; i++) { array[i] = ( i<bigIntLength ? getDigitAtIndex(bigInt, bigIntLength - i -1) :0 ); } return array; } static String add(int bigInt1, int bigInt2) { //Find array length int length1 = intLenght(bigInt1); int length2 = intLenght(bigInt2); int arrayLength = Math.max(length1, length2); int array1[] = intToArray(bigInt1, length1, arrayLength); int array2[] = intToArray(bigInt2, length2, arrayLength); return add(array1, array2); } private static String add(int[] array1, int[] array2) { int carry=0; int addArray[] = new int[array1.length + 1]; for (int i = 0; i < array1.length; i++) { addArray[i] = (array1[i] + array2[i] + carry) % 10 ; carry = (array1[i] + array2[i] + carry) / 10; } addArray[array1.length] = carry; return arrayToString(addArray); } private static int getDigitAtIndex(int longint,int index){ return Integer.parseInt(Integer.toString(longint).substring(index, index+1)); } private static String arrayToString(int[] addArray) { String add = ""; boolean firstNonZero = false; for (int i = addArray.length-1; i >= 0 ; i--) { if(!firstNonZero && (addArray[i]==0)){ continue; } else{ firstNonZero=true; } add += addArray[i]; if((i%3 ==0)&&i!=0){ add +=",";} //formatting } String sumStr = add.length()==0?"0":add; return sumStr; } public static String sub(int bigInt1, int bigInt2) { int length1 = intLenght(bigInt1); int length2 = intLenght(bigInt2); int arrayLength = Math.max(length1, length2); int array1[] = intToArray(bigInt1, length1, arrayLength); int array2[] = intToArray(bigInt2, length2, arrayLength); return sub(array1, array2); } private static String sub(int[] array1, int[] array2) { int carry=0; int sub[] = new int[array1.length + 1]; for (int i = 0; i < array1.length; i++) { sub[i] = (array1[i] - array2[i] + carry) % 10 ; //sum digits + carry; then extract last digit carry = (array1[i] - array2[i] + carry) / 10; //Compute carry } sub[array1.length] = carry; return arrayToString(sub); } public static String mul(int bigInt1, int bigInt2) { int length1 = intLenght(bigInt1), length2 = intLenght(bigInt2), length = Math.max(length1, length2); int array1[] = intToArray(bigInt1, length1, length); int array2[] = intToArray(bigInt2, length2, length); return mul(array1, array2); } private static String mul(int[] array1, int[] array2) { int product[] = new int[array1.length + array2.length]; for(int i=0; i<array1.length; i++){ for(int j=0; j<array2.length; j++){ int prod = array1[i] * array2[j]; int prodLength = intLenght(prod); int prodAsArray[] = intToArray(prod, prodLength, prodLength); for (int k =0; k < prodAsArray.length; k++) { product[i+j+k] += prodAsArray[k]; int currentValue = product[i+j+k]; if(currentValue>9){ product[i+j+k] = 0; int curValueLength = intLenght(currentValue); int curValueAsArray[] = intToArray(currentValue, curValueLength, curValueLength); for (int l = 0; l < curValueAsArray.length; l++) { product[i+j+k+l] += curValueAsArray[l]; } } } } } return arrayToString(product); } public static int div(int bigInt1, int bigInt2) { if ( bigInt2 == 0){ throw new ArithmeticException("Division by 0 is undefined:" + bigInt1+ "/" + bigInt2); } int sign = 1; if(bigInt1 < 0) { bigInt1 = -bigInt1; sign = -sign; } if (bigInt2 < 0){ bigInt2 = -bigInt2; sign = -sign; } int result =0; while (bigInt1 >= 0){ bigInt1 -= bigInt2; result++; } return (result - 1) * sign; } public static String check(String bigInt1, String bigInt2){ int difference; StringBuilder first = new StringBuilder(bigInt1); StringBuilder second = new StringBuilder(bigInt2); if(bigInt1.length()> bigInt2.length()){ difference = bigInt1.length() - bigInt2.length(); for(int x = difference; x > 0; x--){ second.insert(0,"0"); } bigInt2 = second.toString(); return bigInt2; }else { difference = bigInt2.length() - bigInt1.length(); for (int x = difference; x> 0; x--) { first.insert(0, "0"); } bigInt1 = first.toString(); return bigInt1; } } public static int mod(int bigInt1, int bigInt2){ int res = bigInt1 % bigInt2; return (res); } public static void main(String[] args) { int bigInt1 = Integer.parseInt("987888787"); int bigInt2 = Integer.parseInt("444234343"); System.out.println(bigInt1+" + "+bigInt2+" = "+add(bigInt1, bigInt2)); System.out.println(bigInt1+" - "+bigInt2+" = "+sub(bigInt1, bigInt2)); System.out.println(bigInt1+" * "+bigInt2+" = "+mul(bigInt1, bigInt2)); System.out.println(bigInt1+" / "+bigInt2+" = "+div(bigInt1, bigInt2)); System.out.println(bigInt1+" % "+bigInt2+" = "+mod(bigInt1, bigInt2)); } 

}

0
11 . '15 3:47
source share

90! , int [], . , , int [].

, Java, 100! . , .

 public int factoial(int num) { int sum = 0; int[][] dig = new int[3][160]; dig[0][0] = 0; dig[0][1] = 0; dig[0][2] = 1; for (int i = 99; i > 1; i--) { int len = length(i); for (int k = 1; k <= len; k++) { // Sets up multiplication int pos = len - k; dig[1][pos] = ((i / (int) (Math.pow(10, pos))) % 10); } int temp; for (int k = 0; k < len; k++) { // multiplication for (int j = 0; j < 159; j++) { dig[2][k + j] += (dig[1][k] * dig[0][j]); if (dig[2][k + j] >= 10) { dig[2][k + j + 1] += dig[2][k + j] / 10; dig[2][k + j] = dig[2][k + j] % 10; } } } sum = 0; for (int k = 159; k >= 0; k--) { System.out.print(dig[2][k]); dig[0][k] = dig[2][k]; dig[1][k] = 0; sum += dig[2][k]; dig[2][k] = 0; } System.out.println(); } return sum; } 
0
17 . '16 17:41
source share

, , - , .

, , BigInteger.

, . , , . . . . , . - . , , int. StringBuffer. . StringBuffer String.

,

 public String addNumber(String input1,String input2){ int n=0;String tempStr; String one=""; String two=""; if(input1.length()>input2.length()){ n=input1.length()-input2.length(); tempStr=new String(input1); one=new String(input1.substring(n,input1.length())); two=new String(input2); }else{ n=input2.length()-input1.length(); tempStr=new String(input2); one=new String(input2.substring(n,input2.length())); two=new String(input1); } StringBuffer temp=new StringBuffer(); for(int i=0;i<n;i++){ temp.append(tempStr.charAt(i)); } StringBuffer newBuf=new StringBuffer(); int carry=0; int c; for(int i=one.length()-1;i>=0;i--){ int a=Character.getNumericValue(one.charAt(i)); int b=Character.getNumericValue(two.charAt(i)); c=a+b+carry; newBuf.append(""+(c%10)); c=c/10; carry=c%10; } String news=new String(temp); for(int i=news.length()-1;i>=0;i--){ c=(Character.getNumericValue(news.charAt(i)))+carry; newBuf.append(""+(c%10)); c=c/10; carry=c%10; } if(carry==1){ newBuf.append(""+carry); } String newisis=new String(newBuf.reverse()); return newisis; } 
0
04 . '18 5:59
source share



All Articles