Look at this:
* formatting list of variables
* converting character to integer using `charCodeAt`
* preallocating array of required size
* using standard language library API (builtins)
<!-- code -->
function characterToInt(char) {
// 48 is char code of zero.
return char.charCodeAt(0) - 48;
}
function longAdd(lnum, rnum) {
// Here we didn't use lambda function (anonimous) to prevent creating
// additaional objects and give less work to GC.
lnum = lnum.split('').reverse().map(characterToInt);
rnum = rnum.split('').reverse().map(characterToInt);
// With comma as third character you didn't broke approach of formating
// using 2 whitespaces.
var len = Math.max(lnum.length, rnum.length)
, acc = 0
// Allocate required space for an array to prevent reallocation overhead
, res = new Array(len);
for (var i = 0; i < len; ++i) {
var subres = (lnum[i] || 0) + (rnum[i] || 0) + acc;
// Use Math.floor instead of 2 additional operations, as it is library
// function which can be written with some optimizations.
acc = Math.floor(subres / 10);
res[i] = subres % 10;
}
if (acc !== 0) {
res.push(acc);
}
return res.reverse().join('');
}
Possible ways to allocate array of required size:
var a = new Array(size) // 1
var a = []; a.length = size // 2
*Note:* it is not final or most optimized version ever, I have tried to show you set of approached you might want to know to optimize your code even further.
## Benchmark using browser
Just open console in your browser and paste following code
var strAdd = function(lnum, rnum) {
lnum = lnum.split('').reverse();
rnum = rnum.split('').reverse();
var len = Math.max(lnum.length, rnum.length),
acc = 0;
res = [];
for(var i = 0; i < len; i++) {
var subres = Number(lnum[i] || 0) + Number(rnum[i] || 0) + acc;
acc = ~~(subres / 10); // integer division
res.push(subres % 10);
}
if (acc !== 0) {
res.push(acc);
}
return res.reverse().join('');
};
function characterToInt(char) {
return char.charCodeAt(0) - 48;
}
function longAdd(lnum, rnum) {
lnum = lnum.split('').reverse().map(characterToInt);
rnum = rnum.split('').reverse().map(characterToInt);
var len = Math.max(lnum.length, rnum.length)
, acc = 0
, res = new Array(len);
for (var i = 0; i < len; ++i) {
var subres = (lnum[i] || 0) + (rnum[i] || 0) + acc;
acc = Math.floor(subres / 10);
res[i] = subres % 10;
}
if (acc !== 0) {
res.push(acc);
}
return res.reverse().join('');
}
var fib = function(num, add) {
var prev = '1',
curr = '1',
temp;
while (curr.toString().length !== num) {
temp = curr;
curr = add(prev, curr);
prev = temp;
}
return curr;
};
console.time("preallocated");
fib(1000, longAdd);
console.timeEnd("preallocated");
console.time("plain");
fib(1000, strAdd);
console.timeEnd("plain");
My results are:
* Google Chrome 46.0.2490.80
<!-- code -->
preallocated: 1620.238ms
plain: 4311.755ms
* Mozilla Firefox 41.0.2
<!-- code -->
preallocated: 849.72ms
plain: 3747.05ms
## Nodejs and preallocation
Lets start with this test where we conditionally switches allocation from static to dynamic.
var plain = function(lnum, rnum) {
lnum = lnum.split('').reverse();
rnum = rnum.split('').reverse();
var len = Math.max(lnum.length, rnum.length),
acc = 0;
res = [];
for(var i = 0; i < len; i++) {
var subres = Number(lnum[i] || 0) + Number(rnum[i] || 0) + acc;
acc = ~~(subres / 10); // integer division
res.push(subres % 10);
}
if (acc !== 0) {
res.push(acc);
}
return res.reverse().join('');
};
var preallocated = function(lnum, rnum) {
lnum = lnum.split('').reverse();
rnum = rnum.split('').reverse();
var len = Math.max(lnum.length, rnum.length),
acc = 0;
res = [];
if (len > 1000)
res.length = len;
for(var i = 0; i < len; i++) {
var subres = Number(lnum[i] || 0) + Number(rnum[i] || 0) + acc;
acc = ~~(subres / 10); // integer division
if (len > 1000)
res[i] = subres % 10
else
res.push(subres % 10);
}
if (acc !== 0) {
if (len > 1000)
res = res.concat(acc)
else
res.push(acc);
}
return res.reverse().join('');
};
var fib = function(num, add) {
var prev = '1',
curr = '1',
temp;
while (curr.toString().length !== num) {
temp = curr;
curr = add(prev, curr);
prev = temp;
}
return curr;
};
console.time("preallocated");
fib(2000, preallocated);
console.timeEnd("preallocated");
console.time("plain");
fib(2000, plain);
console.timeEnd("plain");
I have results:
$ node /tmp/help.js
preallocated: 1278ms
plain: 4249ms
$ node --version
v0.12.7