Javascript — добавление целых чисел с использованием массивов

#javascript #arrays

#javascript #массивы

Вопрос:

Я использую массив для вычисления больших степеней 2. Массивы дополняют друг друга и послесловия, они вычисляют переносы и повторяют цикл n-1 раз, пока я не получу число в виде массива. Я делаю это для того, чтобы избежать ограничения в 15 цифр, которое имеет JavaScript.

Все работает нормально, как только я достигаю n = 42, где переносы начинают пропускаться, а числа не уменьшаются, что приводит к неправильным ответам.

Я попытался изменить метод, с помощью которого перенос обрабатывается внутри цикла while, с базового сложения на целочисленное деление и модуль Звучит глупо, но я добавил дополнительный цикл, чтобы проверить, не больше ли каких-либо элементов, чем 10, но он их не нашел.

   for (var n = 1; n <= 100; n  ) {
    for (var i = 0, x = [2]; i < n - 1; i  ) { // Loop for amount of times to multiply
      x.unshift(0)
      for (var j = x.length - 1; j > 0; j--) { // Double each element of the array
        x[j]  = x[j]
      }
      for (j = x.length - 1; x[j] > 0; j--) { // Check if element >= 10 and carry
        while (x[j] >= 10) {
          x[j - 1]  = Math.floor(x[j] / 10)
          x[j] = x[j] % 10
        }
      }
      if (x[0] === 0) {
        x.shift()
      }
    }
    console.log('N: '   n   ' Array: '   x)
  }
  

Ожидаемые результаты заключаются в том, что каждый элемент в массиве будет сведен к одному числу и будет «перенесен» на элемент слева от него, например :

 N: 1 Array: 2
N: 2 Array: 4
N: 3 Array: 8
N: 4 Array: 1,6
N: 5 Array: 3,2
N: 6 Array: 6,4
  

но начиная с n = 42, возникает ошибка, выглядящая следующим образом:

 N: 42 Array: 4,2,18,18,0,4,6,5,1,1,1,0,4
N: 43 Array: 8,4,36,36,0,8,12,10,2,2,2,0,8
N: 44 Array: 1,7,5,9,2,1,8,6,0,4,4,4,1,6
N: 45 Array: 2,14,10,18,4,2,16,12,0,8,8,8,3,2
N: 46 Array: 7,0,3,6,8,7,4,4,1,7,7,6,6,4
N: 47 Array: 14,0,7,3,7,4,8,8,3,5,5,3,2,8
  

В чем ошибка, из-за которой это может быть вызвано подобным образом?

Комментарии:

1. Вам действительно следует подумать об использовании BigInt . Теперь у него есть встроенная поддержка за счет использования постфикса n для числовых литералов.

2. Даже не знал, что это существует. Спасибо

3. хотя вам следует использовать BigInt, начиная с вашего алгоритма, не следует ли вам проверять во внутреннем цикле for j > 0 вместо x[j] > 0 ? (строка 8)

4. Вы также всегда можете попытаться выполнить отладку. Код слишком (чрезмерно) сложный, чтобы я мог просто понять и просмотреть его в голове для получения больших чисел. Отлаживая его, вы должны обнаружить проблему за секунду, но в любом случае должен быть лучший способ вычислить это без использования списков.

Ответ №1:

Я думаю, причина, по которой ваш код не работает, заключается в этой строке, for (j = x.length - 1; x[j] > 0; j--) { // Check if element >= 10 and carry которую вы не хотите проверять, x[j] > 0 но j > 0 .

Также ваш второй цикл: for (var i = 0, x = [2]; i < n - 1; i ) { — вам это не нужно, нет причин пересчитывать все на каждой итерации, вы можете использовать предыдущий результат.

Вы также можете удваивать значения таким образом: x = x.map(n => n * 2) (мне кажется, это немного более шаблонно).

И в этом нет необходимости, x[j - 1] = Math.floor(x[j] / 10) это может быть просто x[j - 1] = 1 , поскольку предыдущие числа до 9, удвоенные, они не более 18, так что 1 — единственный случай, если x[j] >= 10 .

Может быть код:

 let x = [2] // starting point
for (var n = 1; n <= 100; n  ) {
  x = [0, ...x].map(n => n * 2)
  for (j = x.length - 1; j > 0; j--) {
    if (x[j] >= 10) {
      x[j - 1]  = 1
      x[j] %= 10
    }
  }
  if (x[0] === 0) {
    x = x.slice(1)
  }
  console.log('N: '   n   ' Array: '   x)
}
  

Ответ №2:

Если все, что вам нужно, это большие степени 2, почему вы проходите через безумную проблему использования списков для вычисления этого? Разве это не то же самое:

 function BigPow2(x, acc=2.0) {
    //document.writeln(acc);
    acc = acc >= 5 ? acc / 5 : acc * 2;
    return x <= 1 ? acc : BigPow2(x-1, acc);
}
  

Или, в качестве альтернативы, использовать BigInt?