Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Ада и другие языки _ Ну очень длинные числа

Автор: blackhard 3.05.2008 18:37

В общем суть задания это создание калькулятора который смогбы вычислить 99999999999! ну или 23142342342314234231423142343214*4325234534532534523443.Примерно так.Я решил подобные числа хранить в массивах типа int.Даже написал уже 2 ф.и для сложения и вычитания таких чисел(Но вот только если для беззнаковых), а вот как быть со знаком?Я подумал сделать так если перед первым числом стоит знак - то из 0 вычесть значение 1го элемента массива в который я это число помещаю.Разумно ли сделать так?И еще 1 вопрос никак не мгу сообразить как осуществить операцию ! при подобном представлении числа ?

Вот вобщемто то что я уже написал.



#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<conio.h>
#include<ctype.h>
#include"TARASOV_ERROR.h"

#define KOL 5
#define STRLEN 50000
#define OSN 10

FILE *fo,*fi;

char *sim[KOL]={"+",
"-",
"*",
"/",
"!"};
char answer[STRLEN];
int num1[STRLEN],num2[STRLEN],res[STRLEN],*n1=num1,*n2=num2,*r=res,q,e,k,w1,w2,i;
char oper[STRLEN],*op=oper,c;

int showstring(const char *str)
{
char strASCII[STRLEN];
CharToOem (str,strASCII);
printf("%s\t",strASCII);
return 0;
}
int summa()
{

e=0;
while(w1||w2){
q=(*n1--)+(*n2--)+e;
if(q>9){q%=OSN;*r++=q;e=1;}
else{*r++=q;e=0;}
if(w1>0)w1--;
if(w2>0)w2--;
i++;
}
if(e==1){*r++=e;i++;}
for(i--;i!=-1;i--)
printf("%d",res[i]);
printf("\n");
return 0;
}
int subtract()
{
e=0;
r=res;
i=w1;
while(w1){
*n1+=e;
if(*n1<*n2){*r++=(*n1--)+OSN-(*n2--);e=-1;}
else {*r++=(*n1--)-(*n2--);e=0;}
w1--;
}
while(res[i]==0)i--;
for(i;i!=-1;i--)
printf("%d",res[i]);
printf("\n");
return 0;
}
void multiple()
{

}
void DIV()
{

}
void Fact()
{

}
int main()
{

w1=0;w2=0;

fo=fopen("outtext.txt","w");
if((fi=fopen("in.txt","r"))==NULL)exit(Error(2,"in.txt"));

while(c!=EOF)
{
memset(num1,0,sizeof(num1));
memset(num2,0,sizeof(num2));
memset(res,0,sizeof(res));
memset(oper,0,sizeof(oper));
c=getc(fi);
while(isspace©)c=getc(fi);
if(c==EOF){fclose(fi);return 0;}
while(isalnum©){
w1++;
*n1++=c-'0';
c=fgetc(fi);}
n1--;
while(isspace©)c=getc(fi);
while(!isspace©&&c!=';'&&!isdigit©){
*op++=c;
c=fgetc(fi);}
*op--=0;
while(isspace©)c=getc(fi);
while(c!=';'){
w2++;
*n2++=c-'0';
c=fgetc(fi);}
n2--;
for(k=0;k<KOL;k++)
if(*op==*sim[k])break;
switch(k)
{
case 0:summa();
break;
case 1:subtract();
break;
case 2: multiple();
break;
case 3: DIV();
break;
case 4: Fact();
fprintf(fo,"%s",answer);
break;
}
//}
}


// printf("%d",num1[4]);
fclose(fi);
fclose(fo);
return 0;
}


Автор: first_day 3.05.2008 19:02

Цитата
И еще 1 вопрос никак не мгу сообразить как осуществить операцию ! при подобном представлении числа ?



Т.е. как факториал находить? Нужно каждый раз умножать "длинное" число на короткое. Изначально записываешь в массив 1, а цикл начинаешь от 2 до n, и каждый раз умножаешь свой массив с конечным ответом на параметр цикла.

Автор: blackhard 4.05.2008 1:31

Цитата(first_day @ 3.05.2008 16:02) *

Т.е. как факториал находить? Нужно каждый раз умножать "длинное" число на короткое. Изначально записываешь в массив 1, а цикл начинаешь от 2 до n, и каждый раз умножаешь свой массив с конечным ответом на параметр цикла.

По ходу дела n это мое длинное число -1 ? Но подобное число не может быть параметром цикла оноже слишком большое.

Автор: volvo 4.05.2008 2:21

blackhard, пишешь функцию для уменьшения длинного числа на 1, и функцию, проверяющую, равно ли длинное число нулю... После этого задача вычисления становится тривиальной: копируешь число, от которого надо считать факториал в доп. переменную (далее - "переменная цикла"), и на каждой итерации:
1) переменная цикла = 0? Да -> заканчиваем цикл...
Нет:
2) умножаешь переменную цикла на переменную-результат (произведение остается в переменной-результате)
3) уменьшаешь переменную цикла на 1

(изначально переменная-результат должна быть равна 1)... После окончания цикла в переменной-результате будет то, что тебе нужно.

Как перемножать длинное число на длинное - можешь посмотреть в FAQ-е по Паскалю "Длинная арифметика".

Если б ты делал это на С++, то можно было бы привести пару ссылок на хорошие классы для работы с длинными целыми, но раз у тебя чистый С - не буду...

Автор: blackhard 7.05.2008 22:12

С фактариалом благополучно разобрался.Спасибо за помощь!Теперь понял что несовсем понимаю как сделать деление.Смотрел тут http://forum.pascal.net.ru/index.php?showtopic=2428&hl=%C4%EB%E8%ED%ED%E0%FF+%E0%F0%E8%F4%EC%E5%F2%E8%EA%E0 , но чето неразобрался в алгоритме.Можете разъяснить как про факториал ?

Автор: Bo2nik 7.05.2008 23:01

Цитата(blackhard @ 7.05.2008 19:12) *

Теперь понял что несовсем понимаю как сделать деление.


Можно посмотреть в книге С.Окулов "Программирование в алгоритмах" там вроде всё расписано.

Автор: volvo 7.05.2008 23:06

Вот тут алгоритм расписан автором: http://comp-science.narod.ru/DL-AR/okulov.htm (см. "Седьмая задача. Деление двух длинных чисел, т.е. нахождение целой части частного и остатка.")