Skip to content

Instantly share code, notes, and snippets.

@utahta
Created December 13, 2011 09:15
Show Gist options
  • Save utahta/1471340 to your computer and use it in GitHub Desktop.
Save utahta/1471340 to your computer and use it in GitHub Desktop.
階乗計算1
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
typedef struct mulnum_t{
int32_t fig; // 桁
char *data; // 整数データ
int32_t size; // 確保したメモリのサイズ
}mulnum;
void mul_init(mulnum *num, int32_t size)
{
num->data = (char *)calloc(size, sizeof(char));
num->size = size;
num->fig = 1;
}
void mul_term(mulnum *num)
{
num->fig = 0;
num->size = 0;
free(num->data);
num->data = NULL;
}
void mul_debug(mulnum *num)
{
printf("%d : ", num->fig);
int32_t i=0;
for(i = num->fig-1; i >= 0; --i){
printf("%d", num->data[i]);
}
printf("\n");
}
void mul_set_val(mulnum *num, int32_t val)
{
num->fig = 1;
num->data[num->fig-1] = val % 10;
int32_t tmp = val / 10;
while(tmp > 0){
num->fig++;
num->data[num->fig-1] = tmp % 10;
tmp = tmp / 10;
}
}
void mul_set_num(mulnum *num, mulnum *val)
{
num->fig = val->fig;
memmove(num->data, val->data, num->fig);
}
void mul_add_num(mulnum *num, mulnum *val)
{
int32_t i = 0;
for(i = 0; i < val->fig; ++i){
int32_t tmp = num->data[i] + val->data[i];
if(tmp >= 10){
num->data[i] = tmp % 10;
int32_t idx = i+1;
while(1){
if(num->data[idx] < 9){
if(num->fig < idx+1){
num->fig = idx+1;
}
num->data[idx]++;
break;
}
else{
num->data[idx] = 0;
idx++;
}
}
}
else{
if(num->fig < i+1){
num->fig = i+1;
}
num->data[i] = tmp;
}
}
}
void mul_mul(mulnum *num, int32_t max)
{
mulnum nmax;
mul_init(&nmax, 30);
mul_set_val(&nmax, max);
mulnum base;
mul_init(&base, num->fig+1);
mul_set_num(&base, num);
mulnum tmp;
mul_init(&tmp, num->fig+nmax.fig+1);
int32_t i = 0;
for(i = 0; i < nmax.fig; ++i){
tmp.fig = 1;
int32_t carry = 0;
int32_t len = base.fig;
int32_t fig = i;
int32_t j = 0;
for(j = 0; j < len; ++j){
int32_t val = base.data[j] * nmax.data[i] + carry;
int32_t idx = j+i;
++fig;
if(val >= 10){
tmp.data[idx] = val % 10;
carry = val / 10;
if(len == j+1 && carry > 0){
len++;
}
}
else{
tmp.data[idx] = val;
carry = 0;
}
}
tmp.fig = fig;
if(i == 0){
mul_set_num(num, &tmp);
}
else{
mul_add_num(num, &tmp);
}
}
mul_term(&tmp);
mul_term(&base);
mul_term(&nmax);
}
void mul_kaijou(mulnum *num, int32_t max)
{
int32_t i = 0;
for(i = 1; i <= max; ++i){
mul_mul(num, i);
}
}
void mul_result(mulnum *num)
{
int32_t count = 0;
int32_t i = 0;
for(i = 0; i < num->fig; ++i){
if(num->data[i] != 0) break;
++count;
}
printf("%u %u\n", num->fig, count);
}
int main(int argc, char **argv)
{
int32_t max = 1;
if(argc > 1){
max = atoi(argv[1]);
if(max < 0){
max = 0;
}
if(max > 10000000){
max = 10000000;
}
}
mulnum num;
mul_init(&num, 100000000);
mul_set_val(&num, 1);
mul_kaijou(&num, max);
mul_result(&num);
mul_term(&num);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment