|
Вопрос # 3 759/ вопрос открыт / |
|
Доброго времени суток, уважаемые эксперты!
Попалась задачка, думал легкая, однако повозился значительно, может и для вас покажется интересной.
Задача проста найти факториал 2010.
Все известные типы чисел неподдерживают такое количество символов. В голову пришло считать разрядно т.е:
если 1ый разряд, состоящий из 9ти символов, переполняется то переполняемую единицу переношу во второй разряд и т.д
I1:=I1*I;
if I1 div 1000000000>0 then
begin
I2:= I2*I+(I1 div 1000000000);
I1:=I1 mod 1000000000;
if I2 div 100000000>0 then ...
все это внутри цикла i:=0 to 2010, I1..I12 -12 9ти разрядных(в моем случае) числел. Алгоритм вроде вернуый но после 40! заходит в 0 хотя предел в 12*9 символов не пройден, ошибок в нем нет(все повторяется подобно).
Подумал, может тут помогут, да и вообще заинтересует эта задача=) Спасибо.
З.Ы второй алгоритм выглядет более компактно но почему то условие игнорируется даже при True значении, тут надеюсь подскажите мой косяк в процедуре.
Приложение: Переключить в обычный режим- procedure TForm3.Button1Click(Sender: TObject);
- var
- I1,I2,I3,I4,I5,I6,I7,I8,I9,I10,I11,I12:int64;
- I,S:integer;
- St:string;
- begin
- I1:=1;
- I2:=0;
- I3:=0;
- I4:=0;
- I5:=0;
- I6:=0;
- I7:=0;
- I8:=0;
- I9:=0;
- I10:=0;
- I11:=0;
- I12:=0;
- for i := 1 to 2022 do
- begin
- I1:=I1*I;
-
- if I1 div 1000000000>0 then
- begin
- I2:= I2*I+(I1 div 1000000000);
- I1:=I1 mod 1000000000;
- if I2 div 100000000>0 then
- begin
- I3:= I3*I+(I2 div 1000000000);
- I2:=I2 mod 1000000000;
- if I3 div 100000000>0 then
- begin
-
- I4:= I4*I+(I3 div 1000000000);
- I3:=I3 mod 1000000000;
- if I4 div 100000000>0 then
- begin
-
- I5:= I5*I+(I4 div 1000000000);
- I4:=I4 mod 1000000000;
- if I5 div 100000000>0 then
- begin
-
- I6:= I6*I+(I5 div 1000000000);
- I5:=I5 mod 1000000000;
- if I6 div 100000000>0 then
- begin
-
- I7:= I7*I+(I6 div 1000000000);
- I6:=I6 mod 1000000000;
- if I7 div 100000000>0 then
- begin
-
- I8:= I8*I+(I7 div 1000000000);
- I7:=I7 mod 1000000000;
- if I8 div 100000000>0 then
- begin
-
- I9:= I9*I+(I8 div 1000000000);
- I8:=I8 mod 1000000000;
- if I9 div 100000000>0 then
- begin
-
- I10:= I10*I+(I10 div 1000000000);
- I9:=I9 mod 1000000000;
- if I10 div 100000000>0 then
- begin
-
- I11:= I11*I+(I10 div 1000000000);
- I10:=I10 mod 1000000000;
- if I11 div 100000000>0 then
-
- I12:= I12*I+(I11 div 1000000000);
- I11:=I11 mod 1000000000;
- end;
- end;
- end;
- end;
- end;
- end;
- end;
- end;
- end;
- Edit1.Text:=Inttostr(I1);
- Edit2.Text:=Inttostr(I2);
- Edit3.Text:=Inttostr(I3);
- Edit4.Text:=Inttostr(I4);
- Edit5.Text:=Inttostr(I5);
- Edit6.Text:=Inttostr(I6);
- Edit7.Text:=Inttostr(I7);
- Edit8.Text:=Inttostr(I8);
- Edit9.Text:=Inttostr(I9);
- Edit10.Text:=Inttostr(I10);
- Edit11.Text:=Inttostr(I11);
- Edit12.Text:=Inttostr(I12);
- memo1.Lines.Add(Edit6.Text+Edit5.Text+Edit4.Text+Edit3.Text+Edit2.Text+Edit1.Text);
- end;
- end;
-
-
- procedure TForm3.TryAnother;
- var
- T:array [1..11] of integer;
- i,x,tc:integer;
- str:string;
- begin
- T[1]:=1;
- for x := 2 to 11 do
- begin
- T[x]:=0;
- end;
- for i := 1 to 20 do
- begin
- for tc := 0 to 10 do
- T[1]:=T[1]*I;
- if (T[tc] div 1000000000)>0 then
- begin
- T[TC+1]:= T[tc+1]*I+(T[TC] div 1000000000);
- T[Tc]:=T[tc] mod 1000000000;
- end;
- end;
- for x := 0 to 11 do
- begin
- Str:=str+(inttostr(T[11-x]));
- memo1.Text:=str;
- end;
 |
Вопрос задал: TeM (статус: Посетитель)
Вопрос отправлен: 11 февраля 2010, 22:01
Состояние вопроса: открыт, ответов: 1.
|
Ответ #1. Отвечает эксперт: min@y™
Вот тебе решение: модуль для работы с большими числами.
Цитата:
Это модуль для работы с очень большими числами без потери точности. Модуль даёт возможность манипулирования с 10000 и более значащими цифрами в числах. В модуле реализованы сложение, вычитание, умножение, деление, возведение в целую степень и факториал. Все функции в качестве аргументов принимают длинные строки и результат выдают тоже в виде строки.
 |
Ответ отправил: min@y™ (статус: Доктор наук)
Время отправки: 12 февраля 2010, 08:25
Оценка за ответ: 4
Комментарий к оценке: Недумал что эта тема есть в FAQ, спс
|
Мини-форум вопроса
Всего сообщений: 3; последнее сообщение — 12 февраля 2010, 10:53; участников в обсуждении: 3.
|
Мережников Андрей (статус: Абитуриент), 12 февраля 2010, 05:45 [#1]:
решение этой задачи рассматривалось в журнале "Квант" году этак в 1988. Для хранения больших чисел использовались строковые переменные.
|
|
Егор (статус: 10-ый класс), 12 февраля 2010, 06:21 [#2]:
Цитата (TeM):
I1,I2,I3,I4,I5,I6,I7,I8,I9,I10,I11,I12:int64;
...
I1:=1;
I2:=0;
I3:=0;
I4:=0;
I5:=0;
I6:=0;
I7:=0;
I8:=0;
I9:=0;
I10:=0;
I11:=0;
I12:=0; в те далёкие-далёкие времена, когда люди ещё не изобрели массивы...
или навеяно моим ответом на вопрос вопрос 3718?
Опасайтесь багов в приведенном выше коде; я только доказал корректность, но не запускал его.
— Donald E. Knuth.
|
|
TeM (статус: Посетитель), 12 февраля 2010, 10:53 [#3]:
Егор, первый алгоритм расписан полностью чтобы проследить наличие всевоззможных ошибок, если посмотреть второй алгоритм, то в нем видна и работа с массивом и решение "нагруженности" кода.
Андрей, в 1988 году небыло у меня журналов вообще=)Хранить в строковых переменных конечно можно, но как же потом с ними работать если длина числового значения всеравно лимитирована(только если по частям из строки выбирать числа и их перемножать замещая ответом умноженные величины?).
Min@y™, спасибо, сейчас попробую разобраться.
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|