1000! и вывести дело на экран?
От: NewMan21  
Дата: 12.02.03 21:19
Оценка:
У меня было задание сделать факториал 1000 и вывести все это безобразие в файл. А вот про алгоритм на C или Pascal'e мне что-то и не дался. Может кто подсказать как такое сотворить, а то что-то памяти на рекурсивную функцию не хватает, а разрядов в самой большой переменной — тоже. А выводить еще нужно нормальными числами (не 12+e33 или типа того)
Кто может написать алгоритм? Можно в C, Pascal, PHP
как же это все захватывает!
Re: 1000! и вывести дело на экран?
От: MAN2 Россия http://gameinator.wp-club.net
Дата: 12.02.03 23:39
Оценка:
Здравствуйте, NewMan21, Вы писали:

NM>У меня было задание сделать факториал 1000 и вывести все это безобразие в файл. А вот про алгоритм на C или Pascal'e мне что-то и не дался. Может кто подсказать как такое сотворить, а то что-то памяти на рекурсивную функцию не хватает, а разрядов в самой большой переменной — тоже. А выводить еще нужно нормальными числами (не 12+e33 или типа того)

NM>Кто может написать алгоритм? Можно в C, Pascal, PHP

Попробуй умножение столбиком... через массивы...
Должно спасти. И подойдёт для супер-гигантских чисел.
Re: 1000! и вывести дело на экран?
От: Avvaron  
Дата: 13.02.03 03:17
Оценка:
Здравствуйте, NewMan21, Вы писали:

NM>У меня было задание сделать факториал 1000 и вывести все это безобразие в файл. А вот про алгоритм на C или Pascal'e мне что-то и не дался. Может кто подсказать как такое сотворить, а то что-то памяти на рекурсивную функцию не хватает, а разрядов в самой большой переменной — тоже. А выводить еще нужно нормальными числами (не 12+e33 или типа того)

NM>Кто может написать алгоритм? Можно в C, Pascal, PHP

рассматривай числа в виде строчек и умножай их столбиком — поразрядно.
Re: 1000! и вывести дело на экран?
От: DOOM Россия  
Дата: 13.02.03 04:31
Оценка:
Здравствуйте, NewMan21, Вы писали:

NM>У меня было задание сделать факториал 1000 и вывести все это безобразие в файл. А вот про алгоритм на C или Pascal'e мне что-то и не дался. Может кто подсказать как такое сотворить, а то что-то памяти на рекурсивную функцию не хватает, а разрядов в самой большой переменной — тоже. А выводить еще нужно нормальными числами (не 12+e33 или типа того)

NM>Кто может написать алгоритм? Можно в C, Pascal, PHP

Почитай Кнута 2-й том. Он почти полностью посвящен арифметике
Re: 1000! и вывести дело на экран?
От: Kh_Oleg  
Дата: 13.02.03 09:15
Оценка:
Здравствуйте, NewMan21, Вы писали:

NM>У меня было задание сделать факториал 1000 и вывести все это безобразие в файл. А вот про алгоритм на C или Pascal'e мне что-то и не дался. Может кто подсказать как такое сотворить, а то что-то памяти на рекурсивную функцию не хватает, а разрядов в самой большой переменной — тоже. А выводить еще нужно нормальными числами (не 12+e33 или типа того)

NM>Кто может написать алгоритм? Можно в C, Pascal, PHP
А вот на Лиспе можно посчитать 1000! при помощи обычного рекурсивного алгоритма. И вывести нормальными числами хоть на экран, хоть в файл. Мне удавалось посчитать даже 3500!
Re[2]: 1000! и вывести дело на экран?
От: =KRoN= Россия http://balancer.da.ru
Дата: 13.02.03 10:07
Оценка: 9 (1)
NM>>У меня было задание сделать факториал 1000
KO>А вот на Лиспе можно посчитать 1000! при помощи обычного рекурсивного алгоритма.

2NM: Когда напишешь такое на обычном ЯВУ, интересно посмотреть на скорость. Потому, как на Хаскелле

fact n = if n > 1 then n * fact(n-1) else 1
main = print(fact 1000)


выдаёт
4023872600770937735437024339230039857193748642107146325437999104299385123
9862902059204420848696940480047998861019719605863166687299480855890132382
9669944590997424504087073759918823627727188732519779505950995276120874975
4624970436014182780946464962910563938874378864873371191810458257836478499
7701247663288983595573543251318532395846307555740911426241747434934755342
8646576611667797396668820291207379143853719588249808126867838374559731746
1360853795345242215865932019280908782973084313928444032812315586110369768
0135730421616874760967587134831202547858932076716913244842623613141250878
0208000261683151027341827977704784635868170164365024153691398281264810213
0927612448963599287051149649754199093422215668325720808213331861168115536
1583654698404670897560290095053761647584772842188967964624494516076535340
8198901385442487984959953319101723355556602139450399736280750137837615307
1277619268490343526252000158885351473316117021039681759215109077880193931
7811419454525722386554146106289218796022383897147608850627686296714667469
7562911234082439208160153780889893964518263243671616762179168909779911903
7540312746222899880051954444142820121873617459926429565817466283029555702
9902432415318161721046583203678690611726015878352075151628422554026517048
3304226143974286933061690897968482590125458327168226458066526769958652682
2728070757813918581788896522081643483448259932660433676601769996128318607
8838615027946595513115655203609398818061213855860030143569452722420634463
1797460594682573103790084024432438465657245014402821885252470935190620929
0231364932734975655139587205596542287497740114133469627154228458623773875
3823048386568897646192738381490014076731044664025989949022222176590433990
1886018566526485061799702356193897017860040811889729918311021171229845901
6419210688843871218556461249607987229085192968193723886426148396573822911
2312502418664935314397013742853192664987533721894069428143411852015801412
3344828015051399694290153483077644569099073152433278288269864602789864321
1390835062170950025973898635542771967428222487575867657523442202075736305
6949882508796892816275384886339690995982628095612145099487170124451646126
0379029309120889086942028510640182154399457156805941872748998094254742173
5824010636774045957417851608292301353580818400969963725242305608559037006
2427124341690900415369010593398383577793941097002775347200000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000

практически мгновенно
...Глубина-глубина, я не твой...
Re: 1000! и вывести дело на экран?
От: siavol Россия  
Дата: 13.02.03 10:57
Оценка:
Здравствуйте, NewMan21, Вы писали:

NM>У меня было задание сделать факториал 1000


Кнут конечно дело хорошее, но его еще нужно иметь, так что можешь посмотреть здесь
... << RSDN@Home 1.0 beta 5 >>
Re[2]: 1000! и вывести дело на экран?
От: mihailik Украина  
Дата: 13.02.03 16:02
Оценка:
MAN>Попробуй умножение столбиком... через массивы...
MAN>Должно спасти. И подойдёт для супер-гигантских чисел.

Только не нужно использовать текстовое представление. Нужно использовать массив из 16-битовых unsigned-ячеек.

Другими словами, разряды нужно брать не десятичные, а 65536-ичные. А так всё как обычно: преобразовываем в более широкий формат (32-битное unsigned), перемножаем. Произведение режем на две части: младшие 16 бит — результат, всё что в старших — идёт "в уме".
... << RSDN@Home 1.0 beta 6a >>
Re[3]: 1000! и вывести дело на экран?
От: =KRoN= Россия http://balancer.da.ru
Дата: 13.02.03 16:10
Оценка:
M>Другими словами, разряды нужно брать не десятичные, а 65536-ичные

Почему не 32-х битные? Умножение/деление же прекрасно и с 64-хбитным представлением в EDX:EAX работает.
...Глубина-глубина, я не твой...
Re[4]: 1000! и вывести дело на экран?
От: mihailik Украина  
Дата: 13.02.03 16:20
Оценка:
M>>Другими словами, разряды нужно брать не десятичные, а 65536-ичные

=KR>Почему не 32-х битные? Умножение/деление же прекрасно и с 64-хбитным представлением в EDX:EAX работает.

Скорее всего, на большинстве компьютеров 32-битное умножение будет быстрее 64-битного.
... << RSDN@Home 1.0 beta 6a >>
Re[5]: 1000! и вывести дело на экран?
От: =KRoN= Россия http://balancer.da.ru
Дата: 13.02.03 17:14
Оценка:
M>Скорее всего, на большинстве компьютеров 32-битное умножение будет быстрее 64-битного.

"Дефолтовое" умножение в 32-хбитной Intel-программе перемножает 32-хбитные числа с 64-хбитным результатом (в EDX:EAX). Всё остальное, ИМХО, будет приводить только к снижению скорости, т.к., минимум потребуются префиксы 16-битных операций, максимум — ещё вручную нарезать/маскировать числа.
...Глубина-глубина, я не твой...
Re[6]: 1000! и вывести дело на экран?
От: mihailik Украина  
Дата: 14.02.03 10:13
Оценка:
M>>Скорее всего, на большинстве компьютеров 32-битное умножение будет быстрее 64-битного.

=KR>"Дефолтовое" умножение в 32-хбитной Intel-программе перемножает 32-хбитные числа с 64-хбитным результатом (в EDX:EAX). Всё остальное, ИМХО, будет приводить только к снижению скорости, т.к., минимум потребуются префиксы 16-битных операций, максимум — ещё вручную нарезать/маскировать числа.

Звучит убедительно. Правда, это на ассемблере. Как будет дело с "нормальными ЯВУ", не знаю. Нужно измерять. Интуиция мне подсказывает, что 16-бит разряды и 32-бит умножение будет быстрее 32-бит разрядов и 64-бит умножения.

В Delphi/С++, конечно, можно и asm-вставку сделать. Хотя, для простой домашней программы...
... << RSDN@Home 1.0 beta 6a >>
Re[7]: 1000! и вывести дело на экран?
От: Balancer Россия http://balancer.da.ru
Дата: 15.02.03 16:43
Оценка:
M>Звучит убедительно. Правда, это на ассемблере. Как будет дело с "нормальными ЯВУ", не знаю.

За Дельфи не поручусь, хотя, вроде, Борданд там, наконец-то, смог разродиться неплохим компилятором, а вот компиляторц VC7 давно можно доверять

M>Нужно измерять. Интуиция мне подсказывает, что 16-бит разряды и 32-бит умножение будет быстрее 32-бит разрядов и 64-бит умножения.


#include <stdio.h>

void main(void)
{
    unsigned short a16,b16,c16,d16;
    unsigned long  a32,b32,c32,d32;
    scanf("%d %d"  ,&a16,&b16);
    scanf("%ld %ld",&a32,&b32);

    unsigned long tmp32=(unsigned long)a16*b16;
    d16=tmp32;
    c16=tmp32>>16;

    printf("%d %d\n", c16, d16);
    
    unsigned __int64 tmp64=(unsigned __int64)a32*b32;
    d32=tmp64;
    c32=tmp64>>32;

    printf("%ld %ld", c32, d32);
}


Имеем следующий ассемблерный код (только то, что интересно и несколько упрощено — имена переменных и т.п.):

; 10   :     unsigned long tmp32=(unsigned long)a16*b16;

    movzx   eax, _a16
    movzx   ecx, _b16
    imul    eax, ecx

; 11   :     d16=tmp32;
; 12   :     c16=tmp32>>16;
; 13   : 
; 14   :     printf("%d %d\n", c16, d16);

    movzx   edx, ax
    push    edx
    shr     eax, 16            ; 00000010H
    push    eax
    push    OFFSET s16 ; тут строка вывода
    call    _printf

; 15   :     
; 16   :     unsigned __int64 tmp64=(unsigned __int64)a32*b32;

    mov     eax, _a32
    mul     _b32

; 17   :     d32=tmp64;
; 18   :     c32=tmp64>>32;
; 19   : 
; 20   :     printf("%ld %ld", c32, d32);

    push    eax
    push    edx
    push    OFFSET s32 ; тут строка вывода
    call    _printf


Как видно, даже по числу операций работа с long'ами оказывается выгоднее. Ну неродные для IA32 16-битные числа А если ещё учесть, что за одну операцию обрабатывается вдвое большее число, то выигрышь становится совсем серьёзным

Хотя при отработке этого примера, едва ли не в первый раз столкнулся со случаем, который VC7 не осилил Я изначально делал разбиение произведения двойной точности на компоненты стандартной разрядности через / и % — хотел посмотреть, потянет ли оптимизацию компилятор. В случае 16-битных чисел результат был подобным, а вот для 32-х битных он вызвал библиотечную подпрограмму деления 64-хбитного числа... Пришлось пример оптимизировать уже вручную
...Глубина-глубина, я не твой...
Re[8]: 1000! и вывести дело на экран?
От: Balancer Россия http://balancer.da.ru
Дата: 15.02.03 16:45
Оценка:
Да, все эти извращения с scanf'ом и printf'ом нужны из-за того же большого ума компилятора. Если числа задать заранее, то он результат посчитает на этапе компиляции, если не выводить — то всё, что не используется, он и считать не станет
...Глубина-глубина, я не твой...
Re[2]: 1000! и вывести дело на экран?
От: Demiurg  
Дата: 17.02.03 12:16
Оценка:
Здравствуйте, Kh_Oleg, Вы писали:

KO>Здравствуйте, NewMan21, Вы писали:


KO>А вот на Лиспе можно посчитать 1000! при помощи обычного рекурсивного алгоритма. И вывести нормальными числами хоть на экран, хоть в файл. Мне удавалось посчитать даже 3500!


Так Лисп же имеет только интерфейс рекурсивный, по-моему... Сам все вычисляет он итеративно.
Re[3]: 1000! и вывести дело на экран?
От: bkat  
Дата: 17.02.03 12:48
Оценка:
D> Так Лисп же имеет только интерфейс рекурсивный, по-моему... Сам все вычисляет он итеративно.

Зависит от реализации... Если интерпретатор лиспа может развернуть рекурсию в обычный цикл,
то он делает это (как один из методов оптимизации). А в общем случае это не делается
Re[3]: 1000! и вывести дело на экран?
От: Balancer Россия http://balancer.da.ru
Дата: 17.02.03 13:09
Оценка:
KO>>А вот на Лиспе можно посчитать 1000! при помощи обычного рекурсивного алгоритма. И вывести нормальными числами хоть на экран, хоть в файл. Мне удавалось посчитать даже 3500!
D> Так Лисп же имеет только интерфейс рекурсивный, по-моему... Сам все вычисляет он итеративно.

На Хаскелле и 10000! посчитать можно Секунд 10 думает... :D Впрочем, это тоже наследник Лиспа...
...Глубина-глубина, я не твой...
Re: 1000! и вывести дело на экран?
От: Spark  
Дата: 18.02.03 10:40
Оценка:
Здравствуйте, NewMan21, Вы писали:

NM>У меня было задание сделать факториал 1000 и вывести все это безобразие в файл. А вот про алгоритм на C или Pascal'e мне что-то и не дался. Может кто подсказать как такое сотворить, а то что-то памяти на рекурсивную функцию не хватает, а разрядов в самой большой переменной — тоже. А выводить еще нужно нормальными числами (не 12+e33 или типа того)

NM>Кто может написать алгоритм? Можно в C, Pascal, PHP

Если тема еще актуальна, то вот работающий код.
Правда для расчета 1000! не хватает разрядности, но можно увеличить:
(С) "Советы по Дельфи от Валентина Озерова"

unit HugeInts;

{$DEFINE HugeInt_128}

interface

const
  {$IFDEF HugeInt_128 }
  HugeIntSize = 128;
  {$ELSE}{$IFDEF HugeInt_64 }
  HugeIntSize = 64;
  {$ELSE}{$IFDEF HugeInt_32 }
  HugeIntSize = 32;
  {$ELSE}{$IFDEF HugeInt_16 }
  HugeIntSize = 16;
  {$ELSE}
  HugeIntSize = 8;
  {$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}

  HugeIntMSB  = HugeIntSize-1;

type
  HugeInt = array[0..HugeIntMSB] of Byte;

const
  HugeIntCarry: Boolean = False;
  HugeIntDiv0:  Boolean = False;


procedure HugeInt_Min(var a: HugeInt);                 { a := -a }
procedure HugeInt_Inc(var a: HugeInt);                 { a := a + 1 }
procedure HugeInt_Dec(var a: HugeInt);                 { a := a - 1 }

procedure HugeInt_Add(a, b: HugeInt; var R: HugeInt);  { R := a + b }
procedure HugeInt_Sub(a, b: HugeInt; var R: HugeInt);  { R := a - b }
procedure HugeInt_Mul(a, b: HugeInt; var R: HugeInt);  { R := a * b }
procedure HugeInt_Div(a, b: HugeInt; var R: HugeInt);  { R := a div b }
procedure HugeInt_Mod(a, b: HugeInt; var R: HugeInt);  { R := a mod b }

function HugeInt_IsNeg(a: HugeInt): Boolean;
function HugeInt_Zero(a: HugeInt): Boolean;
function HugeInt_Odd(a: HugeInt): Boolean;

function HugeInt_Comp(a, b: HugeInt): Integer;          {-1:a< 0; 1:a>}
procedure HugeInt_Copy(Src: HugeInt; var Dest: HugeInt);{ Dest := Src }

procedure String2HugeInt(AString: string; var a: HugeInt);
procedure Integer2HugeInt(AInteger: Integer; var a: HugeInt);
procedure HugeInt2String(a: HugeInt; var S: string);

implementation
{$R+}

procedure HugeInt_Copy(Src: HugeInt; var Dest: HugeInt);
{ Dest := Src }
begin
Move(Src, Dest, SizeOf(HugeInt));
end;{ HugeInt_Copy }

function HugeInt_IsNeg(a: HugeInt): Boolean;
begin

HugeInt_IsNeg := a[HugeIntMSB] and $80 > 0;
end;{ HugeInt_IsNeg }

function HugeInt_Zero(a: HugeInt): Boolean;
var i: Integer;
begin

HugeInt_Zero := False;
for i := 0 to HugeIntMSB do
if a[i] <> 0 then Exit;
HugeInt_Zero := True;
end;{ HugeInt_Zero }

function HugeInt_Odd(a: HugeInt): Boolean;
begin

HugeInt_Odd := a[0] and 1 > 0;
end;{ HugeInt_Odd }

function HugeInt_HCD(a: HugeInt): Integer;
var i: Integer;
begin

i := HugeIntMSB;
while (i > 0) and (a[i] = 0) do Dec(i);
HugeInt_HCD := i;
end;{ HugeInt_HCD }

procedure HugeInt_SHL(var a: HugeInt; Digits: Integer);
begin
if Digits > HugeIntMSB then
FillChar(a, SizeOf(HugeInt), 0)
else if Digits > 0 then
begin
Move(a[0], a[Digits], HugeIntSize-Digits);
FillChar(a[0], Digits, 0);
end;{ else if }
end;{ HugeInt_SHL }

procedure HugeInt_SHR(var a: HugeInt; Digits: Integer);
begin
if Digits > HugeIntMSB then
FillChar(a, SizeOf(HugeInt), 0)
else if Digits > 0 then
begin
Move(a[Digits], a[0], HugeIntSize-Digits);
FillChar(a[HugeIntSize-Digits], Digits, 0);
end;{ else if }
end;{ HugeInt_SHR }

procedure HugeInt_Inc(var a: HugeInt);
{ a := a + 1 }
var

i: Integer;
h: Word;
begin

i := 0; h := 1;
repeat
h := h + a[i];
a[i] := Lo(h);
h := Hi(h);
Inc(i);
until (i > HugeIntMSB) or (h = 0);
HugeIntCarry := h > 0;
{$IFOPT R+ }
if HugeIntCarry then RunError(215);
{$ENDIF}
end;{ HugeInt_Inc }

procedure HugeInt_Dec(var a: HugeInt);
{ a := a - 1 }
var Minus_1: HugeInt;
begin

{ naiue i?inoie niinia }
FillChar(Minus_1, SizeOf(HugeInt), $FF); { -1 }
HugeInt_Add(a, Minus_1, a);
end;{ HugeInt_Dec }

procedure HugeInt_Min(var a: HugeInt);
{ a := -a }
var i: Integer;
begin

for i := 0 to HugeIntMSB do
a[i] := not a[i];
HugeInt_Inc(a);
end;{ HugeInt_Min }

function HugeInt_Comp(a, b: HugeInt): Integer;
{ a = b: ==0; a > b: ==1; a < b: ==-1 }
var

A_IsNeg, B_IsNeg: Boolean;
i:                Integer;
begin

A_IsNeg := HugeInt_IsNeg(a);
B_IsNeg := HugeInt_IsNeg(b);
if A_IsNeg xor B_IsNeg then
if A_IsNeg then HugeInt_Comp := -1
else HugeInt_Comp := 1
else
begin
if A_IsNeg then HugeInt_Min(a);
if B_IsNeg then HugeInt_Min(b);
i := HugeIntMSB;
while (i > 0) and (a[i] = b[i]) do Dec(i);
if A_IsNeg then { iaa io?eoaoaeuiua! }
if a[i] > b[i] then HugeInt_Comp := -1
else if a[i] < b[i] then HugeInt_Comp := 1
else HugeInt_Comp := 0
else { iaa iiei?eoaeuiua }
if a[i] > b[i] then HugeInt_Comp := 1
else if a[i] < b[i] then HugeInt_Comp := -1
else HugeInt_Comp := 0;
end;{ else }
end;{ HugeInt_Comp }

procedure HugeInt_Add(a, b: HugeInt; var R: HugeInt);
{ R := a + b }
var

i: Integer;
h: Word;
begin

h := 0;
for i := 0 to HugeIntMSB do
begin
h := h + a[i] + b[i];
R[i] := Lo(h);
h := Hi(h);
end;{ for }
HugeIntCarry := h > 0;
{$IFOPT R+ }
if HugeIntCarry then RunError(215);
{$ENDIF}
end;{ HugeInt_Add }

procedure HugeInt_Sub(a, b: HugeInt; var R: HugeInt);
{ R := a - b }
begin
HugeInt_Min(b);
HugeInt_Add(a, b, R);
end;{ HugeInt_Sub }

procedure HugeInt_Mul(a, b: HugeInt; var R: HugeInt);
{ R := a * b }
var

i, j, k:          Integer;
A_end, B_end:     Integer;
A_IsNeg, B_IsNeg: Boolean;
h:                Word;
begin

A_IsNeg := HugeInt_IsNeg(a);
B_IsNeg := HugeInt_IsNeg(b);
if A_IsNeg then HugeInt_Min(a);
if B_IsNeg then HugeInt_Min(b);
A_End := HugeInt_HCD(a);
B_End := HugeInt_HCD(b);
FillChar(R, SizeOf(R), 0);
HugeIntCarry := False;
for i := 0 to A_end do
begin
h := 0;
for j:= 0 to B_end do
if (i + j) < HugeIntSize then
begin
h := h + R[i+j] + a[i] * b[j];
R[i+j] := Lo(h);
h := Hi(h);
end;{ if }
k := i + B_End + 1;
while (k < HugeIntSize) and (h > 0) do
begin
h := h + R[k];
R[k] := Lo(h);
h := Hi(h);
Inc(k);
end;{ while }
HugeIntCarry := h > 0;
{$IFOPT R+}
if HugeIntCarry then RunError(215);
{$ENDIF}
end;{ for }
{ anee ana oi?ioi... }
if A_IsNeg xor B_IsNeg then HugeInt_Min(R);
end;{ HugeInt_Mul }

procedure HugeInt_DivMod(var a: HugeInt; b: HugeInt; var R: HugeInt);
{ R := a div b  a := a mod b }
var

MaxShifts, s, q:  Integer;
d, e:             HugeInt;
A_IsNeg, B_IsNeg: Boolean;
begin

if HugeInt_Zero(b) then
begin
HugeIntDiv0 := True;
Exit;
end{ if }
else HugeIntDiv0 := False;
A_IsNeg := HugeInt_IsNeg(a);
B_IsNeg := HugeInt_IsNeg(b);
if A_IsNeg then HugeInt_Min(a);
if B_IsNeg then HugeInt_Min(b);
if HugeInt_Comp(a, b) < 0 then

FillChar(R, SizeOf(R), 0)
else
begin
FillChar(R, SizeOf(R), 0);
repeat
Move(b, d, SizeOf(HugeInt));

MaxShifts := HugeInt_HCD(a) - HugeInt_HCD(b);
s := 0;
while (s <= MaxShifts) and (HugeInt_Comp(a, d) >= 0) do
begin
Inc(s);
HugeInt_SHL(d, 1);
end;{ while }
Dec(s);
{ Nicaaai iiao? eiie? b }
Move(b, d, SizeOf(HugeInt));
{ Ia?aiauaai (naaeaaai) d }
HugeInt_ShL(d, S);

Move(d, e, SizeOf(HugeInt));
HugeInt_Min(e);
Q := 0;
{ iiea a >= d au?eneyai a := a+-d e i?e?aueaaai Q}
while HugeInt_Comp(a, d) >= 0 do
begin
HugeInt_Add(a, e, a);
Inc(Q);
end;{ while }

if HugeInt_IsNeg(a) then
begin
HugeInt_Add(a, d, a);
Dec(Q);
end;{ if }
HugeInt_SHL(R, 1);
R[0] := Q;
until HugeInt_Comp(a, b) < 0;
if A_IsNeg xor B_IsNeg then HugeInt_Min(R);
end;{ else }
end;{ HugeInt_Div }

procedure HugeInt_DivMod100(var a: HugeInt; var R: Integer);
var
Q: HugeInt;
S: Integer;
begin

R := 0; FillChar(Q, SizeOf(Q), 0);
S := HugeInt_HCD(a);
repeat
r := 256*R + a[S];
HugeInt_SHL(Q, 1);
Q[0] := R div 100;
R := R mod 100;
Dec(S);
until S < 0;
Move(Q, a, SizeOf(Q));
end;{ HugeInt_DivMod100 }

procedure HugeInt_Div(a, b: HugeInt; var R: HugeInt);
begin

HugeInt_DivMod(a, b, R);
end;{ HugeInt_Div }

procedure HugeInt_Mod(a, b: HugeInt; var R: HugeInt);
begin

HugeInt_DivMod(a, b, R);
Move(a, R, SizeOf(HugeInt));
end;{ HugeInt_Mod }

procedure HugeInt2String(a: HugeInt; var S: string);

function Str100(i: Integer): string;
begin
Str100 := Chr(i div 10 + Ord('0')) + Chr(i mod 10 + Ord('0'));
end;{ Str100 }
var

R:      Integer;
Is_Neg: Boolean;
begin

S := '';
Is_Neg := HugeInt_IsNeg(a);
if Is_Neg then HugeInt_Min(a);
repeat
HugeInt_DivMod100(a, R);
Insert(Str100(R), S, 1);
until HugeInt_Zero(a) or (Length(S) = 254);
while (Length(S) > 1) and (S[1] = '0') do Delete(S, 1, 1);
if Is_Neg then Insert('-', S, 1);
end;{ HugeInt2String }

procedure String_DivMod256(var S: string; var R: Integer);
var Q: string;
begin

FillChar(Q, SizeOf(Q), 0);
R := 0;
while S <> '' do
begin
R := 10*R + Ord(S[1]) - Ord('0'); Delete(S, 1, 1);
Q := Q + Chr(R div 256 + Ord('0'));
R := R  mod 256;
end;{ while }
while (Q <> '') and (Q[1] = '0') do Delete(Q, 1, 1);
S := Q;
end;{ String_DivMod256 }

procedure String2HugeInt(AString: string; var a: HugeInt);
var

i, h:   Integer;
Is_Neg: Boolean;
begin

if AString = '' then AString := '0';
Is_Neg := AString[1] = '-';
if Is_Neg then Delete(Astring, 1, 1);
i := 0;
while (AString <> '') and (i <= HugeIntMSB) do
begin
String_DivMod256(AString, h);
a[i] := h;
Inc(i);
end;{ while }
if Is_Neg then HugeInt_Min(a);
end;{ String2HugeInt }

procedure Integer2HugeInt(AInteger: Integer; var a: HugeInt);
var Is_Neg: Boolean;
begin

Is_Neg := AInteger < 0;
if Is_Neg then AInteger := -AInteger;
FillChar(a, SizeOf(HugeInt), 0);
Move(AInteger, a, SizeOf(Integer));
if Is_Neg then HugeInt_Min(a);
end;{ Integer2HugeInt }

end.
... << RSDN@Home 1.0 beta 6a >>
Re[2]: 1000! и вывести дело на экран?
От: WolfHound  
Дата: 18.02.03 22:29
Оценка:
Здравствуйте, Spark, Вы писали:

Да вы батенька
#pragma pack(push, 1)
typedef unsigned int uint32;
typedef unsigned __int64 uint64;
struct ui64
{
    union
    {
        struct
        {
            uint32 lo;
            uint32 hi;
        };
        uint64 i64;
    };
};
#pragma pack(pop)
int _tmain(int argc, _TCHAR* argv[])
{
    uint32 arr[10000];
    memset(arr, 0, sizeof(arr));
    arr[0]=1;
    int maxi=0;
    ui64 x;
    for(uint32 n=2;n<=10000;n++)
    {
        int i=0;
        uint32 a=0;
        do
        {
            x.i64=arr[i];
            x.i64*=n;
            arr[i]=x.lo+a;
            a=x.hi;
            i++;
        }
        while(a||i<maxi);
        maxi=i;
    }
    x.i64=0;
    maxi--;
    do
    {
        printf("%X",arr[maxi]);
        maxi--;
    }
    while(maxi>=0);
    printf("%u\n", x.hi);
    return 0;
}

Вот только спать пора...лень в десятичном виде печатать...
... << RSDN@Home 1.0 beta 5 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[3]: 1000! и вывести дело на экран?
От: Spark  
Дата: 19.02.03 11:04
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Да вы батенька

А Вы весьма проницательны

Ваш код без сомнения краток и лаконичен, но мне показалось, что NewMan21 было бы интересно познакомиться с принципами работы с большими числами. Поэтому я не привел ему процедуру расчета факториала, а дал исходник модуля для работы с огромными числами. Этот код, на мой взгляд, является хорошим примером того, как можно решать проблемы подобные сабжу, включая способ приведения больших чисел к десятичному виду.

С уважением, Spark.
... << RSDN@Home 1.0 beta 6a >>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.