0

I'm still learning JavaScript so the code is probably messy but this is my function so far. This function is supposed to multiply the shorter number with the larger number digit by digit, padStart them with '0' and put them in an array to be mapped through to add the digits and make them into a string.

function multiply(a, b) {
  let remCont = 0
  let newNum = ''
  let total = 0
  let padStartNum = 0
  let newArr = []
  let newNumZeros = ''


  if((a.length <= 1 && a[0] === '0')||(b.length <= 1 && b[0] === '0')) {
    return '0'
  }

  if(a.length >= b.length) {
    multiplyNums(a,b)
  } else {
    multiplyNums(b,a)
  }

  function multiplyNums(num1,num2) {
    for(let i = num2.length -1;i >= 0;i--) {
      newNum = ''
      remCont = 0
      for(let x = num1.length - 1;x >= 0; x--) {
          total = parseInt(num1[x])*parseInt(num2[i])
          if(remCont > 0) {
            total += remCont
          }
          remCont = 0
          let strTotal = total.toString()
          if(total >= 10 && strTotal[1] === '0') {
            remCont = parseInt(strTotal[0])
            newNum += '0'
          } else if (total >= 10) {
            remCont = parseInt(strTotal[0])
            newNum += strTotal[1]
          } else {
            newNum += strTotal[0]
          }
        }
        if(remCont > 0) {
        newNum += remCont.toString()
        }
        newNumZeros = newNum.padStart(newNum.length+padStartNum,'0')
        padStartNum++
        finalNum = newNumZeros.split('').reverse().join('')
        newArr.push(finalNum)
      }
    }

    let addTotal = ''
    let remCont2
    let total2
    
    newArr.map(a=>addPad(a))
    function addPad(num) {
      if(addTotal.length >= num.length) {
        padB = num.padStart(addTotal.length,'0')
        addSum(addTotal,padB)
      } else {
        padA = addTotal.padStart(num.length,'0')
        addSum(num,padA)
      }
    }
    
    // let testCaseParsed = 0

    // newArr.map(b=>testCase(b.slice(b.length-3)))
    // function testCase(num) {
    //     testCaseParsed += parseInt(num)
    // }
    // let finalThree = testCaseParsed.toString()

    function addSum(num1,num2) {
      addTotal = ''
      for(let i = num1.length - 1;i >= 0;i--) {
      total2 = 0
      if(num2[i] === '0') {
        total2 = parseInt(num1[i])
      } else {
        total2 = parseInt(num1[i])+parseInt(num2[i])
      }
      if(remCont2 > 0) {
        total2++
      }
      remCont2 = 0
      if(total2 >= 10) {
        remCont2++
        total2 -= 10
      }
      addTotal += total2.toString() 
    }
    if(remCont2 > 0) {
      let lastRem = 1
      addTotal += lastRem.toString()
    }
    addTotal = addTotal.split('').reverse().join('').replace(/^0+/, "")
}
  // if(addTotal.length >= 7) {
  //   let result = addTotal.slice(0,addTotal.length-3) + finalThree
  //   return result
  // }
    return addTotal
}

// console.log(multiply("2" ,"0"))
// console.log(multiply("51", "23"))
// console.log(multiply("9", "9"))
// console.log(multiply("311", "692"))
// console.log(multiply("1009", "03"))
// console.log(multiply("5009", "932"))
// Supposed to be: 4668388
// console.log(multiply("210", "613"))
// console.log(multiply("1020303004875647366210", "2774537626200857473632627613"))
// Supposed to be: "2830869077153280552556547081187254342445169156730"
// console.log(multiply("9007199254740991", "9007199254740991"))
// Supposed to be: "81129638414606663681390495662081"
// console.log(multiply("58608473622772837728372827", "7586374672263726736374"))
// Supposed to be: "444625839871840560024489175424316205566214109298"

I've tried this as is and the issue that I get is that the number at the end will be off by 1 so I tried just slicing the result till like the last 3 digits and adding in the last 3 numbers of the addition back in and it worked but then I ran into an issue where for other really big numbers the fourth to the last digit was missing and yet for others it worked like 6 or so failed out of like 100. I tried scrapping that idea and went back to the original code here but I'm confused where this difference of 1 comes from. I've also commented out what I've been trying to do to fix the last digits being different since that didn't work either.

Dave Park
  • 3
  • 2
  • see these: [Fast bignum square computation](https://stackoverflow.com/q/18465326/2521214) and [Modular arithmetics and NTT (finite field DFT) optimizations](https://stackoverflow.com/q/18577076/2521214) – Spektre Jun 07 '23 at 06:18

1 Answers1

1

The problem is that remCont2 may have a nonzero value when addSum returns, and this value creeps into the next call of addSum.

These kinds of problems will never occur if you take the habit of declaring all your variables in the scope where they are needed:

  • Don't let JavaScript implicitly define variables as globals. In your code this happens for finalNum, padA, and padB. This is bad practice. Always define your variables with let or const. If you would run your code in strict mode (with "use strict" at the top), your code would not parse.

  • Define variables that are only used in one statement block (like a function body), as local variables in that block. You have this wrong for many variables, and so also for remCont2: Remove let remCont2 where you have it now, and in addPad start with let remCont2 = 0;.

Some other remarks:

  • Avoid that your functions have side effects. Don't let them modify variables that live outside their scope. Instead have those functions return the result they provide. It is for the caller of that function to potentially aggregate that result into their own variables. For instance, addSum should not mutate addTotal. It should not even read it. It should only return the sum of the two arguments it got, and it is for the caller to capture that result. Do the same with the other functions.

  • End your statements with semicolons. The JavaScript engine has an algorithm to insert missing semicolons, but its rules can have surprising effects and you wouldn't be the first fall for one of its traps. It is better practice to take control and place them yourself.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • Thank you it fixed the issue. I didn't realize the variable remCont2 was leaking over somehow since it was only 1 number at the end that was different. I need to work on getting used to defining my variables inside the scope they're used in. I just got lazy and put them as global since I never knew when I'd use them again in the code. – Dave Park Jun 07 '23 at 06:33