Я пытаюсь вычислить 100!
Я ищу простейший способ выполнить это с помощью C. Я читал, но не нашел конкретного ответа.
Если вы должны знать, я программирую в Xcode в Mac os X.
Спасибо!
Я пытаюсь вычислить 100!
Я ищу простейший способ выполнить это с помощью C. Я читал, но не нашел конкретного ответа.
Если вы должны знать, я программирую в Xcode в Mac os X.
Спасибо!
Если вы ищете простую библиотеку, libtommath (из libtomcrypt), вероятно, вы хотите.
Если вы хотите написать простую реализацию самостоятельно (либо в качестве учебного упражнения, либо потому, что вам нужен только очень ограниченный набор функций bigint и не хотите ссылаться на зависимость от большой библиотеки, загрязнения пространства имен, и т.д.), я мог бы предложить следующее для вашей проблемы:
Поскольку вы можете связать размер результата на основе n
, просто предварительно выделите массив uint32_t
требуемого размера, чтобы сохранить результат. Я предполагаю, что вы захотите напечатать результат, поэтому имеет смысл использовать базу, мощность 10 (т.е. базовую 1000000000), а не мощность 2. То есть каждый элемент вашего массива разрешен для сохранения значения от 0 до 999999999.
Чтобы умножить это число на (нормальное, не большое) целое число n
, выполните следующее:
uint32_t carry=0;
for(i=0; i<len; i++) {
uint64_t tmp = n*(uint64_t)big[i] + carry;
big[i] = tmp % 1000000000;
carry = tmp / 1000000000;
}
if (carry) big[len++] = carry;
Если вы знаете, что n
никогда не будет больше 100 (или небольшого числа), и вы хотите избежать перехода в 64-битный диапазон (или если вы на 64-битной платформе и хотите использовать uint64_t
для вашего массива bigint), затем сделайте базу меньшей мощностью 10, чтобы результат умножения всегда соответствовал типу.
Теперь печать результата - это что-то вроде:
printf("%lu", (long)big[len-1]);
for(i=len-1; i; i--) printf("%.9lu", (long)big[i-1]);
putchar('\n');
Если вы хотите использовать мощность 2 в качестве базы, а не мощность 10, умножение становится намного быстрее:
uint32_t carry=0;
for(i=0; i<len; i++) {
uint64_t tmp = n*(uint64_t)big[i] + carry;
big[i] = tmp;
carry = tmp >> 32;
}
if (carry) big[len++] = carry;
Однако печать вашего результата в десятичном формате будет не так приятна...:-) Конечно, если вы хотите получить результат в шестнадцатеричном формате, то это легко:
printf("%lx", (long)big[len-1]);
for(i=len-1; i; i--) printf("%.8lx", (long)big[i-1]);
putchar('\n');
Надеюсь, это поможет! Я оставлю реализацию других вещей (например, добавление, умножение 2-х бинтов и т.д.) В качестве упражнения для вас. Подумайте только, как вы научились делать базовое 10 дополнение, умножение, деление и т.д. В старшей школе и научить компьютер, как это сделать (но в базе-10 ^ 9 или base-2 ^ 32 вместо), и вы должны не имеют проблем.
Если вы хотите использовать реализацию библиотеки, стандартная, по-видимому, GMP
mpz_t out;
mpz_init(out);
mpz_fac_ui(out,100);
mpz_out_str(stdout,10,out);
должен рассчитать 100! от просмотра документов.
Вы также можете использовать OpenSSL bn; он уже установлен в Mac OS X.
Вы попросили простейший способ сделать это. Итак, вот вы:
#include <gmp.h>
#include <stdio.h>
int main(int argc, char** argv) {
mpz_t mynum;
mpz_init(mynum);
mpz_add_ui(mynum, 100);
int i;
for (i = 99; i > 1; i--) {
mpz_mul_si(mynum, mynum, (long)i);
}
mpz_out_str(stdout, 10, mynum);
return 0;
}
Я протестировал этот код и дал правильный ответ.