Created
December 3, 2016 21:35
-
-
Save ejaszewski/ac3481c0a3afbb7490b0fb4f289d0dc2 to your computer and use it in GitHub Desktop.
Faster Alternative to Java's BigInteger Class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class BigInt { | |
protected long[] digits; | |
protected int length; | |
protected boolean negative; | |
public BigInt(int value) { | |
this((long)value); | |
} | |
public BigInt(long value) { | |
if(value < 0) { | |
value = -value; | |
negative = true; | |
} else | |
negative = false; | |
length = (int)Math.ceil((Math.log10(value) + 1) / 18); | |
digits = new long[length]; | |
int i = 0; | |
for(; value != 0; value /= 1000000000000000000L) | |
digits[i++] = value % 1000000000000000000L; | |
} | |
public BigInt(String s) { | |
negative = s.startsWith("-"); | |
s = s.replaceFirst("-", ""); | |
length = (int)Math.ceil(s.length() / 18.0); | |
digits = new long[length]; | |
int j = 0; | |
for(int i = s.length() - 18; i > -1; i -= 18) | |
digits[j++] = Long.parseLong(s.substring(i, i + 18)); | |
if(s.length() % 18 != 0) | |
digits[j] = Long.parseLong(s.substring(0, s.length() % 18)); | |
} | |
public String toString() { | |
StringBuilder str = new StringBuilder(); | |
for(int i = length - 1; i > -1; i--) { | |
if(i != length - 1) | |
str.append(String.format("%018d", digits[i])); | |
else | |
str.append(digits[i]); | |
} | |
str.insert(0, negative ? "-" : ""); | |
return str.toString(); | |
} | |
public void add(BigInt other) { | |
if(negative == other.negative) | |
addUnsigned(other); | |
} | |
private void addUnsigned(BigInt other) { | |
if(length < other.length) | |
if(digits.length < (other.length + 1)) | |
realloc(other.length + 1); | |
if(digits.length < length + 1) | |
realloc(length + 1); | |
length++; | |
long carry = 0; | |
for(int i = 0; i < Math.min(length, other.length); i++) { | |
long nval = digits[i] + other.digits[i] + carry; | |
carry = nval / 1000000000000000000L; | |
digits[i] = nval % 1000000000000000000L; | |
} | |
for(int i = Math.min(length, other.length); i < Math.max(length, other.length); i++) { | |
digits[i] += carry; | |
carry = digits[i] / 1000000000000000000L; | |
if(carry == 0) | |
break; | |
} | |
if(digits[length - 1] == 0) | |
length--; | |
} | |
private void realloc(int newSize) { | |
if(length > newSize) | |
return; | |
long[] newArr = new long[newSize]; | |
System.arraycopy(digits, 0, newArr, 0, length); | |
digits = newArr; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment