function parseInt10(i) {
if (isNumber(i)) {
return Math.floor(i);
}
else {
return parseInt(i);
}
}
var numRegExp = /^[+-]?(0[box]?)?\w*$/;
function checkRadixAndNumber(s, radix) {
if (!numRegExp.test(s)) {
throw new Error("Input first param must be a number string and and sign only one +/-!.");
}
s = toLowerCase(s);
var sign = '+';
if (eq(s.charAt(0), '-')) {
sign = '-';
s = s.substring(1);
} else if (eq(s.charAt(0), '+')) {
// sign = '+';
s = s.substring(1);
}
if (eq(s.charAt(0), '0')) {
var radixI = 8;
s = s.substring(1);
if (eq(s.charAt(0), 'o')) {
// radix = 8;
s = s.substring(1);
}
else if (eq(s.charAt(0), 'x')) {
radixI = 16;
s = s.substring(1);
} else if (eq(s.charAt(0), 'b')) {
radixI = 2;
s = s.substring(1);
} else if (eq(len(s), 0)) {
radixI = radix;
}
radix = radixI;
}
if (!radix || lt(radix, 2) || gt(radix, 36)) {
throw new Error("Radix between 2 and 36.");
}
for (var i = 0; i < len(s); i++) {
if (nlt(digitsMap.get(s.charAt(i)), radix)) {
throw new Error("Input number cannot greater than radix: " + radix);
}
}
s = str2ListBySeparator(s, '');
s = clearOpenZeroI(s);
return [list2StrWithJoint(s, ''), radix, sign];
}
function checkBigIntegerNumber10(a) {
if (oExist(a) && oExist(a.length)) {
for (var i = 0; i < len(a); i++) {
if (!((a[i] >= 0 && a[i] <= 9) || (a[i] >= '0' && a[i] <= '9'))) {
throw "Not a integer number string."
}
}
} else {
throw "Not a integer number string.";
}
}
function initZero(nums) {
for (var i = 0; i < len(nums); i++) {
nums[i] = 0;
}
}
function clearOpenZeroI(nums) {
var openZero = 0;
while (eq(nums[openZero], 0)) {
openZero++;
}
nums = nums.slice(openZero);
if (eq(len(nums), 0)) {
nums = [0];
}
return nums;
}
function clearOpenZeroS(nums) {
var openZero = 0;
while (eq(nums[openZero], '0')) {
openZero++;
}
nums = nums.slice(openZero);
if (eq(len(nums), 0)) {
nums = '0';
}
return nums;
}
var int10RegExp = /^[+-]?\d*$/;
function whatSign(s) {
return s.startsWith('-') ? '-' : '+';
}
function getRidOfSign(s) {
if (eq(s.charAt(0), '-')) {
s = s.substring(1);
} else if (eq(s.charAt(0), '+')) {
s = s.substring(1);
}
return s;
}
/**
*
* @param {String} a
* @param {String} b
*/
function addInt10(a, b) {
//check decimal format
if (!(int10RegExp.test(a) && int10RegExp.test(b))) {
throw new Error("params must be decimal number and sign only one +/-!");
}
//calc sign
var asign = whatSign(a);
var bsign = whatSign(b);
a = getRidOfSign(a);
b = getRidOfSign(b);
checkBigIntegerNumber10(a);
checkBigIntegerNumber10(b);
a = clearOpenZeroS(a);
b = clearOpenZeroS(b);
//determine end sign
if (eqInt10(a, b) && !eq(asign, bsign)) {
return '0';
}
else if (ltInt10(a, b)) {//a > b ,indeed
var tmp = a;//data swap
a = b;
b = tmp;
tmp = bsign;//sign swap
bsign = asign;
asign = tmp;
}
var finalSign = asign;
var radix = 10;
var nums = EMPTY_VALUES.ARRAY;
var le = pmax(a, b);
nums.length = le + 1;
initZero(nums);
var i = len(a) - 1;
var j = len(b) - 1;
var k = 0;
//core 1
while (i >= 0 && j >= 0) {
if (eq(asign, bsign)) {//for +
nums[k++] = parseInt10(a[i--]) + parseInt10(b[j--]);
} else {//for -
nums[k++] = parseInt10(a[i--]) - parseInt10(b[j--]);
}
}
while (i >= 0) {
nums[k++] = parseInt10(a[i--]);
}
// while (j >= 0) {//this is error,max num rest!!!Do you understand?!!!
// nums[k++] = parseInt10(b[j--]);
// }
// core 2
for (var n = 0; n < len(nums); n++) {
if (eq(asign, bsign)) {//+ handler
if (nums[n] >= radix) {
nums[n + 1] += parseInt10(nums[n] / radix);
nums[n] %= radix;
}
} else {//- handler
if (nums[n] < 0) {//because of '-',don't have num >= radix;
nums[n + 1] -= 1;
nums[n] += radix;
}
}
}
nums.reverse();
nums = clearOpenZeroI(nums);
var s = list2StrWithJoint(nums, '');
if (eq(finalSign, '-')) {
s = '-' + s;
}
return s;
}
/**
*
* @param {String} a
* @param {String} b
*/
function multiplyInt10(a, b) {
if (!(int10RegExp.test(a) && int10RegExp.test(b))) {
throw new Error("params must be decimal number and sign only one +/-!");
}
//calc sign
var asign = whatSign(a);
var bsign = whatSign(b);
a = getRidOfSign(a);
b = getRidOfSign(b);
checkBigIntegerNumber10(a);
checkBigIntegerNumber10(b);
a = clearOpenZeroS(a);
b = clearOpenZeroS(b);
var finalSign = eq(asign, bsign) ? '+' : '-';
var radix = 10;
var nums = EMPTY_VALUES.ARRAY;
// var le = pmax(a, b);
// nums.length = le * 2 + 1;
nums.length = len(a) + len(b);
initZero(nums);
//core 1
var k = 0;
for (var i = len(a) - 1; i >= 0; i--) {
for (var j = len(b) - 1; j >= 0; j--) {
nums[len(a) - 1 - i + k++] += parseInt10(a[i]) * parseInt10(b[j]);
// console.log(len(a) - 1 - i + k - 1, nums[len(a) - 1 - i + k - 1], parseInt10(a[i]), parseInt10(b[j]));
}
k = 0;
}
//core 2
for (var n = 0; n < len(nums); n++) {
if (nums[n] >= radix) {
nums[n + 1] += parseInt10(nums[n] / radix);
nums[n] %= radix;
}
}
nums.reverse();
nums = clearOpenZeroI(nums);
var s = list2StrWithJoint(nums, '');
if (eq(finalSign, '-')) {
s = '-' + s;
}
return s;
}
function addInt10One(s) {
// checkBigIntegerNumber10(s);
return addInt10(s, '1');
}
function compareInt10(a, b) {
checkBigIntegerNumber10(a);
checkBigIntegerNumber10(b);
if (len(a) > len(b)) {
return 1;
} else if (len(a) < len(b)) {
return -1;
}
var i = 0;
while (eq(a[i], b[i]) && i < len(a)) {
i++;
}
if (eq(i, len(a))) {
return 0;
}
else if (a[i] > b[i]) {
return 1;
} else if (a[i] < b[i]) {
return -1;
}
return 0;
}
function gtInt10(a, b) {
return compareInt10(a, b) > 0;
}
function ltInt10(a, b) {
return compareInt10(a, b) < 0;
}
function eqInt10(a, b) {
return eq(compareInt10(a, b), 0);
}
/**
*
* @param {String} s
* @param {String} p
*/
function powerInt10(s, p) {
if (!int10RegExp.test(s)) {
throw new Error("params must be decimal number and sign only one +/-!");
}
var finalSign = whatSign(s);
s = getRidOfSign(s);
checkBigIntegerNumber10(s);
s = clearOpenZeroS(s);
var num = '1';
p = String(p);
for (var i = '0'; ltInt10(i, p); i = addInt10One(i)) {
num = multiplyInt10(num, s);
}
if (eq(finalSign, '-')) {
num = '-' + num;
}
return num;
}
/**
*
* @param {String} a
* @param {String} b
*/
function substractInt10(a, b) {
//check decimal format
if (!(int10RegExp.test(a) && int10RegExp.test(b))) {
throw new Error("params must be decimal number and sign only one +/-!");
}
//calc sign
// var asign = whatSign(a);
var bsign = whatSign(b);
// a = getRidOfSign(a);
b = getRidOfSign(b);
//exchange sign '+' and '-'
b = eq(bsign, '-') ? b : '-' + b;
return addInt10(a, b);
}
/**
*
* @param {String} a
* @param {STring} b
*/
function divideInt10(a, b) {
//check decimal format
if (!(int10RegExp.test(a) && int10RegExp.test(b))) {
throw new Error("params must be decimal number and sign only one +/-!");
}
//calc sign
var asign = whatSign(a);
var bsign = whatSign(b);
a = getRidOfSign(a);
b = getRidOfSign(b);
checkBigIntegerNumber10(a);
checkBigIntegerNumber10(b);
a = clearOpenZeroS(a);
b = clearOpenZeroS(b);
if (eq(b, '0')) {
throw new Error("divisor cannot be zero or 0");
}
var finalSign = eq(asign, bsign) ? '+' : '-';
if (eq(a, '0')) {
return eq(finalSign, '-') ? '-0' : '0';
}
//core
var radix = '10';
var quotient = '0';
while (!(ltInt10(a, b))) {
var rest = String(len(a) - len(b));
var rest10 = powerInt10(radix, rest);
var qn = multiplyInt10(b, rest10);
if (gtInt10(qn, a)) {
rest = substractInt10(rest, '1');
rest10 = powerInt10(radix, rest);
}
qn = multiplyInt10(b, rest10);
a = substractInt10(a, qn);
quotient = addInt10(quotient, rest10);
}
if (eq(finalSign, '-')) {
quotient = '-' + quotient;
}
return quotient;
}
/**
*
* @param {String} a
* @param {String} b
*/
function modInt10(a, b) {
//check decimal format
if (!(int10RegExp.test(a) && int10RegExp.test(b))) {
throw new Error("params must be decimal number and sign only one +/-!");
}
//calc sign
// var asign = whatSign(a);
// var bsign = whatSign(b);
a = getRidOfSign(a);
b = getRidOfSign(b);
checkBigIntegerNumber10(a);
checkBigIntegerNumber10(b);
a = clearOpenZeroS(a);
b = clearOpenZeroS(b);
if (eq(b, '0')) {
throw new Error("divisor cannot be zero or 0");
}
// var finalSign = asign;
if (eq(a, '0')) {
return eq(finalSign, '-') ? '-0' : '0';
}
//core
var radix = '10';
// var quotient = '0';
while (!(ltInt10(a, b))) {
var rest = String(len(a) - len(b));
var rest10 = powerInt10(radix, rest);
var qn = multiplyInt10(b, rest10);
if (gtInt10(qn, a)) {
rest = substractInt10(rest, '1');
rest10 = powerInt10(radix, rest);
}
qn = multiplyInt10(b, rest10);
a = substractInt10(a, qn);
// quotient = addInt10(quotient, rest10);
}
// if (eq(finalSign, '-')) {
// a = '-' + a;
// }
return a;
}
/**
*
* @param {String} a
* @param {String} b
*/
function divideAndRemainderInt10(a, b) {
//check decimal format
if (!(int10RegExp.test(a) && int10RegExp.test(b))) {
throw new Error("params must be decimal number and sign only one +/-!");
}
//calc sign
var asign = whatSign(a);
// var bsign = whatSign(b);
a = getRidOfSign(a);
b = getRidOfSign(b);
checkBigIntegerNumber10(a);
checkBigIntegerNumber10(b);
a = clearOpenZeroS(a);
b = clearOpenZeroS(b);
if (eq(b, '0')) {
throw new Error("divisor cannot be zero or 0");
}
var finalSign = asign;
if (eq(a, '0')) {
return [eq(finalSign, '-') ? '-0' : '0', '0'];
}
//core
var radix = '10';
var quotient = '0';
while (!(ltInt10(a, b))) {
var rest = String(len(a) - len(b));
var rest10 = powerInt10(radix, rest);
var qn = multiplyInt10(b, rest10);
if (gtInt10(qn, a)) {
rest = substractInt10(rest, '1');
rest10 = powerInt10(radix, rest);
}
qn = multiplyInt10(b, rest10);
a = substractInt10(a, qn);
quotient = addInt10(quotient, rest10);
}
if (eq(finalSign, '-')) {
quotient = '-' + quotient;
}
return [quotient, a];
}
/**
*
* @param {String} s
* @param {Number} radix
*/
function radixToInt10(s, radix) {
var result = checkRadixAndNumber(s, radix);
s = clearOpenZeroS(result[0]);
radix = result[1];
var sign = result[2];
//core
if (isNumber(radix) && !eq(radix, 10)) {
var os = '0';
radix = String(radix);
for (var i = len(s) - 1; i >= 0; i--) {
os = addInt10(os,
multiplyInt10(
String(digitsMap.get(s[i])),
powerInt10(radix, len(s) - i - 1)
)
);//have to multiply n*radix^N
}
s = os;
}
if (eq(sign, '-')) {
s = '-' + s;
}
return s;
}
/**
*
* @param {String} s
* @param {Number} radix
*/
function int10ToRadix(s, radix) {
if (!int10RegExp.test(s)) {
throw new Error("params must be decimal number and sign only one +/-!");
}
var sign = whatSign(s);
s = getRidOfSign(s);
checkBigIntegerNumber10(s);
s = clearOpenZeroS(s);
//core
if (isNumber(radix) && !eq(radix, 10)) {
radix = String(radix);
var radixNum = EMPTY_VALUES.ARRAY;
var result = divideAndRemainderInt10(s, radix);
radixNum.push(digits[result[1]]);
while (!eq(result[0], '0')) {
result = divideAndRemainderInt10(result[0], radix);
radixNum.push(digits[result[1]]);
}
radixNum.reverse();
s = list2StrWithJoint(radixNum, '');
}
if (eq(sign, '-')) {
s = '-' + s;
}
return s;
}
function BigInteger(s, radix = 10) {
ntfs(this, BigInteger);
var r = checkRadixAndNumber(s, radix);
this.s = r[0];
this.data = str2ListBySeparator(this.s, '');
this.radix = r[1];
this.sign = r[2];
}
var BigInteger_impl = {
int10: function () {//new bigint obj
return new BigInteger(this.int10Value());
},
intRadix: function (r) {
return new BigInteger(this.intRadixValue(r));
},
intRadixValue: function (r) {
return int10ToRadix(this.int10Value(), r);
},
unsignedInt10Value: function () {//string
// var data = EMPTY_VALUES.ARRAY;
// var s = '0';
// var radix = String(this.radix);
// for (var i = len(this.s) - 1; i >= 0; i--) {
// s = addInt10(s,
// multiplyInt10(
// String(digitsMap.get(this.s[i])),
// powerInt10(radix, len(this.s) - i - 1)
// )
// );//have to multiply n*radix^N
// }
// return s;
return radixToInt10(this.s, this.radix);
},
int10Value: function () {
var sign = this.sign;
if (eq(sign, '+')) {
sign = '';
}
return sign + this.unsignedInt10Value()
},
add: function (a) {
notInstanceof(a, BigInteger, "param must be BigInteger object!");
var aData = a.int10Value();
var oData = this.int10Value();
return new BigInteger(addInt10(aData, oData));
},
multiply: function (a) {
notInstanceof(a, BigInteger, "param must be BigInteger object!");
var aData = a.int10Value();
var oData = this.int10Value();
return new BigInteger(multiplyInt10(aData, oData));
},
substract: function (a) {
notInstanceof(a, BigInteger, "param must be BigInteger object!");
var aData = a.int10Value();
var oData = this.int10Value();
return new BigInteger(substractInt10(aData, oData));
},
divide: function (a) {
notInstanceof(a, BigInteger, "param must be BigInteger object!");
var aData = a.int10Value();
var oData = this.int10Value();
return new BigInteger(divideInt10(oData, aData));
},
mod: function (a) {
notInstanceof(a, BigInteger, "param must be BigInteger object!");
var aData = a.int10Value();
var oData = this.int10Value();
return new BigInteger(modInt10(oData, aData));
},
power: function (n) {
//One:
// var sum = BigInteger.ONE;
// n = String(n);
// for (var i = '0'; ltInt10(i, n); i = addInt10One(i)) {
// sum = sum.multiply(this);
// }
// return sum;
//Two:
return new BigInteger(powerInt10(this.int10Value(), String(n)));
},
negate: function () {
return new BigInteger(
eq(this.sign, '-')
?
'+' + this.unsignedInt10Value()
:
'-' + this.unsignedInt10Value());
},
addOne: function () {
return this.add(BigInteger.ONE);
},
toString: function (r) {
if (isNumber(r) && !eq(this.radix, r)) {
return this.intRadixValue(r);
}
return this.s;
},
// toJSON: function (r) {//JSON.stringify()!
// return this.toString(r);
// }
};
impl(BigInteger, BigInteger_impl);
var BigInteger_static_impl = {
ZERO: new BigInteger('0'),
ONE: new BigInteger('1'),
};
static_impl(BigInteger, BigInteger_static_impl);
a = new xy.BigInteger('123')
a.toString(26) //"4j"
BigInteger