Как умножить массив целых, чтобы получить одно число? - PullRequest
0 голосов
/ 27 июня 2018

Итак, у меня есть один int, разбитый на массив меньших целых. Например, int num = 136928 становится int num[3] = {13,69,28}. Мне нужно умножить массив на определенное число. Нормальная работа будет 136928 * 2 == 273856. Но мне нужно сделать [13,69,28] * 2, чтобы дать тот же ответ, что и 136928 * 2 снова в виде массива - результат должен быть

for(int i : arr) {
  i *= 2;
  //Should multiply everything in the array
  //so that arr now equals {27,38,56}
}

Любая помощь будет благодарна за то, как это сделать (также необходимо работать с умножением плавающих чисел), например. arr * 0.5 должно наполовину все в массиве.

Для тех, кому интересно, число должно быть разбито на массив, потому что оно слишком велико для хранения в любом стандартном типе (64 байта). В частности, я пытаюсь выполнить математическую операцию с результатом хеширования sha256. Хэш возвращает массив хэша как uint8_t[64].

Ответы [ 2 ]

0 голосов
/ 01 июля 2018

Если вам просто нужно умножить на / делить на два (2), вы можете просто сдвинуть биты в каждом байте, составляющем значение.

Так что для умножения вы начинаете слева (я предполагаю здесь большой порядковый номер). Затем вы берете самый старший бит байта и сохраняете его во временной переменной (возможный бит переноса ). Затем вы сдвигаете другие биты влево. Сохраненный бит будет самым младшим битом следующего байта после сдвига. Повторяйте это, пока вы не обработаете все байты. У вас может остаться один бит переноса, который вы можете выбросить, если выполняете операции по модулю 2 ^ 512 (64 байта).

Деление аналогично, но вы начинаете справа и несете младший значащий бит каждого байта. Если вы удалите самый правый бит, то вычислите «пол» вычисления (т. Е. Три, разделенные на два, будут равны одному, а не полутора или двум).


Это полезно, если

  1. Вы не хотите копировать байты или
  2. если вам просто необходимы битовые операции, и вы не хотите включать библиотеку с множественной точностью / большим целым числом.

Рекомендуется использовать большую целочисленную библиотеку для удобства обслуживания.

0 голосов
/ 27 июня 2018

Попробуйте вместо этого использовать Boost.Multiprecision . В частности, тип cpp_int, представляющий целочисленное значение произвольного размера.

//In your includes...
#include <boost/multiprecision/cpp_int.hpp>
//In your relevant code:
bool is_little_endian = /*...*/;//Might need to flip this
uint8_t values[64];
boost::multiprecision::cpp_int value;
boost::multiprecision::cpp_int::import_bits(
    value, 
    std::begin(values), 
    std::end(values), 
    is_little_endian
);
//easy arithmetic to perform
value *= 2;
boost::multiprecision::cpp_int::export_bits(
    value, 
    std::begin(values), 
    8, 
    is_little_endian
);
//values now contains the properly multiplied result

Теоретически это должно работать с типом uint512_t правильного размера, который находится в том же пространстве имен, что и cpp_int, но у меня нет компилятора C ++ для тестирования прямо сейчас, поэтому я не могу проверить. Если это работает, вы должны предпочесть uint512_t, так как это, вероятно, будет быстрее, чем целое число произвольного размера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...