-
Notifications
You must be signed in to change notification settings - Fork 292
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
jspref 比较 #12
Comments
说明一下, 留一个问题:为什么 add 1 的 substr 是 -14 |
再提一点,add1 可以用一个 while 搞定 |
叼叼叼,膜拜大佬 |
话说有同学回答一下-14的问题,和写一个单个while就搞定的算法吗? |
刚才自己跑了一遍代码,才发现自己在群里说的是错的(捂脸,下次不敢没跑代码就乱说了) |
虽然
我改成-15试了下,结果和-14是不一样的 let times = 100;
let numbers1 = '';
let numbers2 = '';
while(--times) {
numbers1 += Math.random();numbers2 += Math.random();
}
numbers1 = numbers1.replace(/\D/g, '');numbers2 = numbers2.replace(/\D/g, '');
const add1 = (x, y) => {
let rs = [];
while (x.length > 0 || y.length > 0) {
rs.push(parseInt(x.substr(-14) || 0, 10) + parseInt(y.substr(-14) || 0, 10));
x = x.substr(0, x.length - 14);
y = y.substr(0, y.length - 14);
}
var u = 0, o = '';
while (rs.length) {
let v = (rs.shift() + u).toString();
o = v.substr(-14) + o;
u = parseInt(v.substr(0, v.length - 14) || 0, 10);
}
return o;
}
const add2 = (x, y) => {
let rs = [];
while (x.length > 0 || y.length > 0) {
rs.push(parseInt(x.substr(-15) || 0, 10) + parseInt(y.substr(-15) || 0, 10));
x = x.substr(0, x.length - 15);
y = y.substr(0, y.length - 15);
}
var u = 0, o = '';
while (rs.length) {
let v = (rs.shift() + u).toString();
o = v.substr(-15) + o;
u = parseInt(v.substr(0, v.length - 15) || 0, 10);
}
return o;
}
console.log(add1(numbers1,numbers2));
console.log(add2(numbers1,numbers2)); |
数字类型通过8字节的 double 浮点型表示,在JS中,使用 Number.MAX_SAFE_INTEGER 可以获得JS最大安全可进行算数运算的最大值范围 => 9007199254740991 十六位整型,因为使用的是浮点数运算会丢失精度,所以大于这个值运算都不对。 由于在第-14位上面有进位的问题,所以按13位进行切分计算,用-15会丢位的。 |
const add1 = (x, y) => { |
666666~ |
不一致是因为有bug,有一定概率会遇到, 我改了一个 split 的版本 const add2 = (x, y) => {
x = '' + x;
y = '' + y;
if (/\D/.test((x + y))) {
return NaN;
}
let output = '';
let carry = '';
let zero = '0000000000000000000000';
const split = (str) => (zero + str).split(/(?=\d{14}$)/);
const remove_left_zero = (str) => ('' + str).replace(/^0+/, '');
while (x.length > 0 || y.length > 0 || carry.length > 0) {
let tx = split(x);
let ty = split(y);
let ta = split(parseInt(tx[1] || 0, 10) + parseInt(ty[1] || 0, 10) + parseInt(carry || 0, 10));
output = ta[1] + output;
carry = ta[0];
x = remove_left_zero(tx[0]);
y = remove_left_zero(ty[0]);
carry = remove_left_zero(carry);
}
return remove_left_zero(output);
} |
var safeLength = 15; // 14 ?
const add1 = (x, y) => {
var sum = ''; // 相加结果
var flag = 0; // 进位
while (x.length > 0 || y.length > 0) {
// 计算最后面safeLength个数字的相加值
var tailX = x.substr(-safeLength) || '0';
var tailY = y.substr(-safeLength) || '0';
var tailSum = (parseInt(tailX) + parseInt(tailY) + flag).toString();
// 前头补齐0(刚好切害到0开头的情况)
var orginLength = Math.max(tailX.length, tailY.length);
if (tailSum.length < orginLength) {
tailSum = '0'.repeat(orginLength - tailSum.length) + tailSum;
}
// 重新计算进位
flag = parseInt(tailSum.substr(0, tailSum.length - safeLength) || 0);
// 除进位之外,添加到结果前面
sum = tailSum.substr(-safeLength) + sum;
// 去掉已计算的最后面safeLength个数字
x = x.substr(0, x.length - safeLength);
y = y.substr(0, y.length - safeLength);
}
// 最后的进位
sum = flag ? flag + sum : sum;
return sum;
}
function add2(a, b) {
var aList = a.split('').reverse();
var bList = b.split('').reverse();
var max = Math.max(aList.length, bList.length);
var cList = [];
var flag = 0;
for (var i = 0; i < max; i++) {
var temp = (+aList[i] || 0) + (+bList[i] || 0) + flag;
flag = 0;
if (temp > 9) {
temp -= 10;
flag = 1;
}
cList.push(temp);
}
if (flag > 0) {
cList.push(flag);
}
return cList.reverse().join('');
}
(function test() {
let times = 100;
let numbers = '';
while(--times) {
numbers += Math.random();
}
numbers = numbers.replace(/\D/g, '');
let counts = 1e5;
while(--counts) {
let x = numbers.substring(Math.random() * 10 >> 0, Math.random() * 30 >> 0);
let y = numbers.substring(Math.random() * 30 >> 0, Math.random() * 80 >> 0);
//x = '1736';
//y = '611111750505538122824820966007687248173708494041043351';
var sum1 = add1(x, y);
var sum2 = add2(x, y);
if (sum1 != sum2) {
console.log('x:' + x);
console.log('y:' + y);
console.log('sum1', sum1);
console.log('sum2', sum2);
}
}
})() |
重来没有考虑过这种运算边界值的问题,还有很多要学啊~膜拜上面的各位大佬! |
https://jsperf.com/calc-add
The text was updated successfully, but these errors were encountered: