x Dismiss
Sign up
3 Why would you want to replace it? Lotfi Mar 15 '11 at 21:09 10
When calculating the factorial of 100 (100!) with
25 s/How/Why/ and you've got a good question. Mark Peters Mar 15 '11 at 21:09 Java using integers I get 0
3 @frodosamoa: 600 is way small. People looking for large prime numbers need millions of digits. John Mar 5
15 '11 at 21:14
How Can I Convert Very Large Decimal Numbers to
1 You could copy the code from BigInteger, removing anything you want to avoid. However you are unlikely to Binary In Java
gain anything and some JVMs provide special handling optimizations for BigInteger/BigDecimal which a copy
of the class is unlikely to enjoy. I would at least read the code for BigInteger before attempting this as it has 0
all the code you appear to need. Peter Lawrey Mar 15 '11 at 21:15 How Do I convert very big String to number in Java
4 The (int) factorial(34) == 0, the (long) factorial(66) == 0, if you only take the last bits of a large number you 4
shouldn't expect to get the right answer. This has been recently covered in
stackoverflow.com/questions/5317732/ Peter Lawrey Mar 15 '11 at 21:39 how to generate random number between 0 and
2^32-1 in java
show 9 more comments
0
adding two very large numbers
6 Answers active oldest votes
5
Implementing BigInteger's multiplyfrom scratch
(and making sure it's O(n^2))
I think a programmer should have implemented his own bignum-library once, so welcome here.
0
212 (Of course, later you'll get that BigInteger is better, and use this, but it is a valuable learning
How to add or subtract very large numbers without
experience.) bigint in C#?
(You can follow the source code of this course life on github. Also, I remade this (a bit polished) into -3
a 14-part blog series.) Factorial calculation
based on the datatypes which Java gives us. see more linked questions
As you think the decimal conversion is the most complicated part, let's stay in a decimal based Related
mode. For efficiency, we'll store not real decimal digits, but work in base 1 000 000 000 = 10^9 <
2^30 . This fits in a Java int (up to 2^31 or 2^32 ), and the product of two such digits fits nicely
in a Java long . 12
C++ handling very large integers
final static int BASE = 1000000000;
final static int BASE_DECIMAL_DIGITS = 9;
872
2009
Do we store the digits in little- or big endian, i.e. the bigger parts first or last? It does not really
Generating random integers in a specific range
matter, so we decide on big-endian since this is how humans want to read it. (For now we
concentrate on non-negative values - later we'll add a sign bit for negative numbers.)
50
For testing purposes, we add a constructor which allows initializing from such a int[].
Large Numbers in Java
/**
* creates a DecimalBigInt based on an array of digits. 10
* @param digits a list of digits, each between 0 (inclusive)
How to add two numbers of any length in java?
* and {@link BASE} (exclusive).
* @throws IllegalArgumentException if any digit is out of range.
*/ 0
public DecimalBigInt(int... digits) {
for(int digit : digits) { How to calculate integer expression in Java
if(digit < 0 || BASE <= digit) {
throw new IllegalArgumentException("digit " + digit +
5
" out of range!");
} Generating very large random numbers java
}
this.digits = digits.clone();
} 1
As a added bonus, this constructor is also usable for a single int (if smaller than BASE ), and Java Annotations for Simple Arithmetic on Non
even for no int (which we'll interpret as 0). So, we now can do this: Primitive Numbers
/** Why does java gives odd results while trying to find
* A simple string view for debugging purposes. out the value of pi using java.math.BigInteger?
* (Will be replaced later with a real decimal conversion.)
*/
public String toString() { Hot Network Questions
return "Big" + Arrays.toString(digits);
Optimal sphere packings ==> Thinnest ball
}
coverings?
The output is now Big[7, 5, 2, 12345] , which is more useful for testing, isn't it? Folding Numbers
Each of our digits is represented by a block of digits in the original number: What's an easy way of making my luggage unique,
so that it's easy to spot on the luggage carousel?
String block = Writing referee report: found major error, now
decimal.substring(Math.max(firstSome + (i-1)*BASE_DECIMAL_DIGITS, 0), what?
firstSome + i *BASE_DECIMAL_DIGITS);
How fast is the free Wi-Fi at Kiev airport?
(The Math.max is needed here for the first shorter block.) We now use the usual Integer parsing Is it a fallacy, and if so which, to believe we are
function, and put the result into the array: special because our existence on Earth seems
improbable?
digits[i] = Integer.parseInt(block); What is the proper position for quick-release
} levers?
Let's see if this works: Tenant claims they paid rent in cash and that it
was stolen from a mailbox. What should I do?
DecimalBigInt d2 = DecimalBigInt.valueOf("12345678901234567890"); What does 'apt-get install update' do?
System.out.println(d2);
Output:
Looks right :-) We should test it with some other numbers (of different length) too.
We need to output our individual digits as 9 decimal digits each. For this we can use the
Formatter class, which supports printf-like format strings.
Addition.
Let's start with addition, as this is simple (and we can use parts of it for the multiplication later).
/**
* calculates the sum of this and that.
*/
public DecimalBigInt plus(DecimalBigInt that) {
...
}
I want method names that you can read like you would read the formula, thus plus , minus ,
times instead of add , subtract , multiply .
So, how does addition work? It works the same as we learned it in school for decimal numbers
higher than 9: add the corresponding digits, and if for some of then the result is bigger than 10 (or
BASE in our case), carry one to the next digit. This can cause the resulting number to have one
digit more than the original ones.
First we look at the simple case that both numbers have same number of digits. Then it looks
simply like this:
(We go from right to left, so we can carry any overflows to the next digit. This would be a bit prettier
if we had decided using Little Endian format.)
If both numbers do not have the same number of digits, it gets a bit more complicated.
This method adds one digit to an element in the array (which may already contain some non-zero
value), and stores the result back in the array. If there was overflow, we carry it to the next digit
(which has index one less, not one more) by means of a recursive call. This way we make sure our
digits stay always in the valid 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 next does the same for a whole array of digits to add:
/**
* 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--;
}
}
/**
* 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];
We could do a bit better here if we would look before if overflow is at all possible and only then
create the array one bigger than necessary.
Ah, one test: d2.plus(d2) gives Big[24, 691357802, 469135780] , which looks right.
Multiplication.
Let's remember back to school, how did we multiply bigger numbers on paper?
123 * 123
----------
369 <== 123 * 3
246 <== 123 * 2
123 <== 123 * 1
--------
15129
So, we have to multiply each digit[i] of the first number with each digit[j] of the second number, and
add the product in digit[i+j] of the result (and pay attention to carry). Of course, here the indexes are
counted from right, not from left. (Now i really wish I had used little-endian numbers.)
Since the product of two of our digits can get outside of the range of int , we use long for
multiplication.
/**
* 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 see why I declared my addDigits method to take a resultIndex parameter. (And I
Now we can see why I declared my addDigits method to take a resultIndex parameter. (And I
just changed the last argument to a varargs parameter, to be able to write this here better.)
I hope I have the index-calculations right. With a little-endian representation, it would have been
multiplyDigit(result, resultIndex + i + j, leftFactor[i], rightFactor[j]) - quite
clearer, isn't it?
Our times method now has only to allocate the result array, invoke 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);
Comparison
How to know if one of our numbers is bigger than another? First, we compare the length of the
arrays. As we took care not to induce any leading zeros (did we?), the longer array should have the
bigger number.
If the length are same, we can compare elementwise. Since we use big endian (i.e. the big end
comes first), we start at the beginning.
If everything was same, obviously our numbers are identical, and we can return 0 .
return 0;
}
equals + hashCode()
Every good immutable class should implement equals() and hashCode() in a suitable (and
compatible) way.
For our hashCode() , we simply sum up the digits, multiplying them with a small prime to make
sure digit-switching does not result in same hash code:
/**
* calculates a hashCode for this object.
*/
public int hashCode() {
int hash = 0;
int hash = 0;
for(int digit : digits) {
hash = hash * 13 + digit;
}
return hash;
}
In the equals() method we simply can delegate to the compareTo method, instead of
implementing the same algorithm again:
/**
* 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, enough for today. Subtraction (and maybe negative numbers) and division are more
complicated, so I'm omitting them for now. For calculating the factorial of 90 this should be
enough.
/**
* 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;
}
This gives us
fac(90) = 1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000
Prompted by the next question of frodosamoa, I wrote my answer about how to convert from
arbitrary (positional) number systems in the one in which we can (or want to) calculate. (In the
example there, I converted from trinary to decimal, while the question was about decimal to binary.)
Here we want to convert from an arbitrary number system (okay, with radix between 2 and 36, so
we can use Character.digit() to convert single digits to ints) to our system with radix BASE (=
1.000.000.000, but this is not really important here).
Basically we use Horner scheme to calculate the value of polynomial with the digits as coefficients
at the point given by the radix.
value = 0;
for i = n .. 0
value = value * radix + digit[i]
return value
Since our input strings are big-endian, we don't have to count down, but can use a simple enhanced
for loop. (It looks more ugly in Java, since we have no operator overloading, and no autoboxing
from int to our DecimalBigInt type.)
In my actual implementation I added some error checking (and exception throwing) to ensure that
we really have a valid number, and of course a documentation comment.
In school, I learned long division. Here is an example for a small (one-digit) divisor, in the notation
we use here in Germany (with annotations about the background calculations, which we normally
would not write), in 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.
Of couse, we don't need to calculate these products (0, 12, 0, 30, 42) and subtract them if we have
a native remainder operation. Then it looks like this (of course, we here would not need to write the
operations):
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.
This already looks quite like short division, if we write it in another format.
If we have a two-digit number x with first digit smaller than our divisor d, than x / d is a one-digit
number, and x % d is also a one-digit number, smaller than d. This, together with induction,
shows that we only ever need to divide (with remainder) two-digit numbers by our divisor.
Coming back to our big numbers with radix BASE: all two-digit numbers are representable as a
Java long , and there we have native / and % .
/**
* 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,
private int divideDigit(int[] result, int resultIndex,
int divident, int lastRemainder,
int divisor) {
assert divisor < BASE;
assert lastRemainder < divisor;
result[resultIndex] = (int)quot;
return (int)rem;
}
We will now call this method in a loop, always feeding the result from the previous call back 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'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;
}
Now we want to have a public method returning a DecimalBigInt, so we create one. It has the task
to check the arguments, create an array for the working method, discard the remainder, and create
a DecimalBigInt from the result. (The constructor removes a 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!");
}
/**
* 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);
}
Now we have the basics to convert to an arbitrary radix. Of course, not really arbitrary, only radixes
smaller than BASE are allowed, but this should not be a too big problem.
As we always need both the quotient and the remainder, we won't use the public methods modulo
and divideBy , but instead repeatedly call the divideDigits method.
/**
* 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!");
}
Then, we create an array for the result digits (long enough), and some other variables.
quotLen is the number of digits (excluding leading zeroes) in the last quotient. If this is 0, we are
done.
while(quotLen > 0) {
The quotient-and-remainder operation. The quotient is now in quot , the remainder in rem .
We put the remainder in the output array (filling it from the last digit).
rDigits[rIndex] = rem;
rIndex --;
current = quot;
If there are leading zeros in the quotient (there will be at most one, since radix is smaller than
BASE), we shrink the quotient size by one. The next array will be smaller.
if(current[0] == 0) {
// omit leading zeros in next round.
quotLen--;
}
}
}
After the loop there may be leading zeros in the rDigits array, and we cut them off.
That's it. It looks a bit complicated, though. Here is an example of how to use it:
/**
* 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();
}
11 Why doesn't this have more upvotes? Terrific answer! Kakira Mar 24 '11 at 8:04
18 wow, longest answer I've ever seen on SO. Eng.Fouad Feb 22 '12 at 4:14
1 @RokKralj Do you have some more detailed critique where I could have written this better?
Palo Ebermann Aug 28 '13 at 17:42
You might want to implement or research a library for binary-coded decimal if you're trying to avoid
BigInteger . You can accomplish factorial of 90 with BigInteger if you want to use it though:
2
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;
}
share improve this answer edited Mar 15 '11 at 22:42 answered Mar 15 '11 at 22:34
share improve this answer edited Mar 15 '11 at 22:42 answered Mar 15 '11 at 22:34
WhiteFang34
43.3k 13 75 93
Ah, I just realized that I implemented a kind of (packed) binary-coded decimal in my answer :-)
Palo Ebermann Mar 16 '11 at 2:11
Arithmetic operations in Java using the operators + , - , * , / , and % are bound by the
constraints of the Java primitive data types.
1
This means that if you can't fit your desired numbers into the range of, say a double or long then
you'll have to use a "big number" library, such as the one built-in to Java (BigDecimal, BigInteger),
or a third-party library, or write your own. This also means that you cannot use the arithmetic
operators since Java does not support operator overloading.
maerics
73.8k 17 148 196
return carryForward(finalNumberInArray);
share improve this answer edited Sep 22 '14 at 7:45 answered Mar 4 '13 at 5:12
}
return Integer.toString(bigInt).length();
}
}
return add(array1, array2);
share }improve this answer edited Sep 12 '15 at 1:33 answered Sep 11 '15 at 3:47
1 The explanation
for (int belongs
i = to0;the
i answer, and not to the comment
< array1.length; i++) { section. And please add further explanation,
code only answers aren't very =helpful.
addArray[i] Mephy Sep
(array1[i] 11 '15 at 3:52
+ array2[i] + carry) % 10 ;
carry = (array1[i] + array2[i] + carry) / 10;
Does this
} implementation of a BigInteger class contribute anything that is not already in another answer?
Teepeemm Sep 12 '15 at 12:36
addArray[array1.length] = carry;
return arrayToString(addArray);
}
Adhyyan Sekhsaria
1
Your Answer
By posting your answer, you agree to the privacy policy and terms of service.
Not the answer you're looking for? Browse other questions tagged java math biginteger integer or
ask your own question.
question feed
about us tour help blog chat data legal privacy policy work here advertising info mobile contact us feedback
Stack Overflow Programmers Database Code Review Photography Academia English Bicycles Mathematics Philosophy Stack Apps
Administrators Language &
Server Fault Unix & Linux Magento Science Fiction more (8) Usage Role- Cross Validated more (3) Meta Stack
Drupal Answers & Fantasy playing (stats) Exchange
Super User Ask Different Signal Skeptics Games
(Apple) SharePoint Processing Graphic Design Theoretical Area 51
Web Mi Yodeya Anime & Computer
Applications WordPress User Experience Raspberry Pi Movies & TV (Judaism) Manga Science Stack
Development Overflow
Ask Ubuntu Mathematica Programming Music: Practice Travel more (18) Physics Careers
Geographic Puzzles & Code & Theory
Webmasters Information Salesforce Golf Christianity MathOverflow
Systems Seasoned
Game ExpressionEngine more (7) Advice English Chemistry
Development Electrical Answers (cooking) Language
Engineering Learners Biology
TeX - LaTeX Cryptography Home
Android Improvement Japanese Computer
Enthusiasts Language Science
Personal
Information Finance & Arqade
Security Money (gaming)
site design / logo 2016 Stack Exchange Inc; user contributions licensed under cc by-sa 3.0 with attribution required
rev 2016.10.7.4047