javascript - JS中如何实现数字乘法

标签 javascript

我想创建一个将数字逐位相乘的函数,就像我们在学校所做的那样。例如,在 445 * 456 中,我们首先将 5 乘以 6,然后将 4 乘以 4,然后将 4 乘以 5,依此类推。我想这样做是为了在字符串中获取非常非常长的乘法的答案。

这里,numArray是数组中存储的数字,例如563是[5,6,3]; 类似地,另一个数字可以是例如621 转换为 [6, 2, 1]

   for(var i = 1; i <= anotherNumArray.length; i++) {
        var multiplier = anotherNumArray[anotherNumArray.length-i]
        for(var j = 1; j <= numArray.length; j++) {
            var multiplicand = numArray[numArray.length-j]
            answer.unshift(multiplicand*multiplier);
   }

我正在尝试循环数字乘法。但我得到了奇怪的结果。

最佳答案

问题比提出的更复杂

假设实际的“长乘法”模拟,即只允许数字乘法和求和,请参阅下面的注释和工作代码。

首先,代码忽略了两个数字的乘法会溢出并产生一个非零进位值的事实,该值应与下一个乘法相加

其次,正如我们在学校学到的那样,对于每个数字,我们都会收到与第二个数字的所有其他数字相乘的新结果。最后我们需要对这些乘法结果求和

下面的代码适用于非负十进制数。它可以简化,但已尽力保持初始算法的精神

// parameters
const lhs = "445";
const rhs = "456";

// utilities
const createZeros = length => new Array(length).fill(0);
const padArrayEnd = (length, padding, array) => [...array, ...createZeros(length - array.length)];
const last = array => array[array.length - 1];

// given a carray and an array of digits, add the carry to the last digit.
// if the result overflows, add the remainder as a new digit instead
// example;
//   array = [3, 4, 5]; addCarry(2, array); array == [3, 4, 7]
//   array = [3, 4, 9]; addCarry(2, array); array == [3, 4, 0, 1]
function addCarry(carry, digits) {
    if (carry == 0) {
        return;
    }

    let value = last(digits) + carry;
    if (value > 10) {
        digits[digits.length - 1] = 0;
        digits.unshift(value % 10);
    } else {
        digits[digits.length - 1] = value;
    }
}

console.log({ message: "start", lhs, rhs });

// state
const answer = [];
const entries = [];
let carry = 0;

// perform digit by digit multiplication.
// remember that the result array for each digit should have N leading zeros, where N is the position of that digit.
// this is the reason we keep an array of entries. each entry, is the result array corresponding to that digit
for(let lcur = 0; lcur < lhs.length; lcur++) {
    const leftDigit = lhs[lhs.length - 1 - lcur];

    // the multiplications entry
    const multiplications = createZeros(lcur);

    for(let rcur = 0; rcur < rhs.length; rcur++) {
        const rightDigit = rhs[rhs.length - 1 - rcur];

        // perform multiplication, but notice that in case of overflow we keep
        // only the ones, and remember carry for next iteration
        const times = (leftDigit * rightDigit) + carry;
        const ones = times % 10;
        carry = Math.floor(times / 10);

        multiplications.unshift(ones);
        console.log({ message: "step", expr: `${leftDigit} * ${rightDigit}`, times, ones, carry });
    }

    if (carry != 0){
        multiplications.unshift(carry);
        carry = 0;
    }

    // update entries
    entries.push(multiplications); 
    console.log({ message: "entry", multiplications });
}

// add the final carry
addCarry(carry, last(entries));

console.log({ message: "entries", entries });

// sum all entries with carries
const maxLength = entries
    .map(entry => entry.length)
    .reduce((acc, entry) => Math.max(acc, entry), 0);

// for convinience, reverse all entries - this can by bypassed with messing around with indices
entries.forEach(entry => entry.reverse());

carry = 0;
for (let idx = 0; idx < maxLength; ++idx) {
    const sum = entries
        .map(entry => entry[idx] || 0)
        .reduce((acc, value) => acc + value, carry);

    const ones = sum % 10;
    carry = Math.floor(sum / 10);

    answer.unshift(ones);
    console.log({ message: "summation", sum, ones, carry, answer });
}

// add final summation carry
// remember that we reversed stuff before, reverse back
// answer.reverse()
addCarry(carry, answer);

// finalize a result 
const result = answer.join("");
const expected = (parseInt(lhs) * parseInt(rhs)).toString(); // string for some reason
console.log({ message: "finish", expr: `${lhs} * ${rhs} = ${answer.join("")}`, answer, expected });

关于javascript - JS中如何实现数字乘法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60852441/

相关文章:

javascript - Apache : CORS header 'Access-Control-Allow-Origin' missing

javascript - Javascript 使 SSL 无效

javascript - 将 dynamodb 响应数据传递给回调函数时出现问题

javascript - 每个组件传递 action() 时出错

javascript - 最简单的 JavaScript HTMLEncode lib/函数实现是什么?

javascript - Vue.js : add data when checked box

javascript - CSS:菜单在悬停时打开并在单击时关闭

javascript - 从数组创建对象到 json 对象

javascript - 如何使用通过 riot.route() 获得的参数?

javascript - 如何更改复选框遵循 JSON 字符串?