Created
December 13, 2011 09:15
-
-
Save utahta/1471340 to your computer and use it in GitHub Desktop.
階乗計算1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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