Как работать с большими целыми числами, которые не вписываются ни в одну из структур данных языка

Я пытаюсь решить предварительные проблемы с программированием и по двум проблемам, которые я должен рассчитать и напечатать очень большие целые числа (например, 100!, 2 ^ 100).

Мне также нужен быстрый способ вычисления степеней этих больших целых чисел.

Можете ли вы посоветовать мне некоторые алгоритмы или структуры данных для этого? (Кстати, я читал раздел C произвольной точности арифметики C-интерфейсов и реализаций, но это не помогает для pow())

EDIT: Я думаю, что возведение в степень методом квадратизации и бит-сдвига будет работать на мощность, но мне также нужен быстрый способ вычисления факториалов для этого ints. Спасибо.

EDIT2: для тех, кто заинтересован;

Найдите кратчайшую длину строки бита, которая включает в себя все битовые строки с длиной N (извините за мой английский, я приведу пример). N < 10000

Например, кратчайшая длина строки бита, которая включает в себя все битовые строки длиной 2 (00, 01, 10, 11), равна 5 (11001).

Мое решение для этой задачи было 2 ^ n + n - 1. (поэтому я должен вычислить степень 2, я думаю, что буду использовать бит-сдвиг)

Другая проблема состоит в том, что с учетом двух длин можно найти, как много разных способов достичь длины N. Например, ввод 10, 2, 3. Затем вам нужно достичь 10 с помощью 2 и 3 (например, 2 + 2 + 2 + 2 + 2, 2 + 2 + 3 + 3, 3 + 2 + 2 + 3, 3 + 3 + 2 + 2...). 1 <= N < 2 ^ 63. Мы вычислим anwser в mod 1000000007.

Мое решение было, 2x + 3y = N, поэтому x = (N - 3y)/2. Для y от 0 до 2 * N/3, если x является целым числом, тогда я должен рассчитать обобщенную перестановку для этих X и Y, total + = (x + y)!/(x! * y!).

Ответы

Ответ 2

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

Ответ 3

Возможно, вы захотите взглянуть на реализацию криптографических программ (особенно GnuPG приходит мне на ум). Причина в том, что криптографические функции также используют очень большие целые числа (так называемые MultiPrecision Integer - MPI). Эти MPI хранятся таким образом, что первые два байта указывают, как размер целого числа и последние байты хранят значение.

GPG является открытым исходным кодом, просто посмотрите на него:)

Ответ 4

Используйте GMP для их обработки. Он имеет встроенную факториальную поддержку и большие возможности и т.д. Он имеет, помимо прочего, интерфейс C и С++. Вам понадобится mpz_t как тип, который содержит очень большие целые числа.

Ответ 5

Для C что-то вроде this будет работать или катится с помощью массивов int или char с пятном в массиве, представляющим цифра. [1 | 0 | 1] или ['1'|'0'|'1'] для 101 и т.д.

Ответ 6

Вы можете сохранить номер в следующем формате: количество цифр и массив цифр этого номера. Это распространенный способ борьбы с большими числами в конкурсах программирования.

Вот класс, чем обеспечивает хранение чисел и умножение. Можно вводить и выводить числа, которые тривиальны.

class huge {
public:
    int size;
    int data[1000];

    friend void mul(const huge &a, int k, huge &c) {
        c.size = a.size;
        int r = 0;
        for (int i = 0; i < a.size; i++) {
            r += a.data[i] * k;
            c.data[i] = r % 10;
            r = r / 10;
        }
        if (r > 0) {
            c.size++;
            c.data[c.size - 1] = r;
        }
        while (c.size > 1 && c.data[c.size - 1] == 0)
            c.size--;
    }

    friend void mul(const huge &a, const huge &b, huge &c) {
        c.size = a.size + b.size;
        memset(c.data, 0, c.size * sizeof(c.data[0]));
        for (int i = 0; i < a.size; i++) {
            int r = 0;
            for (int j = 0; j < b.size; j++) {
                r += a.data[i] * b.data[j] + c.data[i + j];
                c.data[i + j] = r % 10;
                r /= 10;
            }
            if (r > 0)
                c.data[i + b.size] = r;
        }
        while (c.size > 1 && c.data[c.size - 1] == 0)
            c.size--;
    }
};

Ответ 7

Базовая математика может делать умножение любого двойного с двойным...

def biginteger(num1, num2):
result = []
lnum1 = len(num1)
lnum2 = len(num2)

k = x = remainder = 0
while len(result) < lnum1:
    result.append(0)
for i in range(lnum1, 0, -1):
    multiplier = int(num1[i - 1])
    for j in range(lnum2, 0, -1):
        temp = (int(num2[j - 1]) * multiplier) + remainder + int(result[k])
        result[k] = str(temp % 10)
        remainder = temp / 10
        k += 1
    result.append(str(remainder))
    if remainder != 0:
        remainder = 0
    x += 1
    k = x

return ''.join([result[i - 1] for i in range(len(result), 0, -1)])

num1 = '37234234234234'
num2 = '43234234234232'
print biginteger(num1, num2)