Комментарии 22
Ох! Сколько воспоминаний!
В середине 90х написал вычисление 100! на PostScripte.
То есть, файл идёт на принтер, а принтер уже считает 100! сам.
Попробую отыскать.
P.S. По PostScript находится некоторое число статей на Хабр.
2002 год, память подводит:
100!
%!PS-Adobe-2.0 %%Title: N-factorial %%Date: Sun Apr 21 20:30:19 CEST 2002 %%BoundingBox: 0 0 592 792 %%EndComments
% -------------- Variables ---------------
/LM 72 def %right margin
/RM 216 def %left margin
/ypos 720 def %current y-position
/lineheight 14 def %distance between lines
/Tempstr 4 string def
/MAXARRAY 3000 def
/numbers MAXARRAY array def
/N 1000 def
% ------------- Procedures ---------------
/crlf %move to next line
{ ypos lineheight sub %decrease ypos
/ypos exch def % ...& save new value
LM ypos moveto } def %move to next line
/counter 0 def% the number of current factorial because we are calculating
% it step-by-step in the loop
/c2 0 def % pointer of 'number' in array 'numbers';
% needed for adding of 'overflow' to the next cell of array
/number 0 def % current number from array 'numbers'
/cprint 0 def % necessary for printing: to not print some 'zeroes' before
% factorial
%/mult - multiplication of array 'numbers' by 'counter'
/mult
{ 0 1 MAXARRAY -1 add
{dup numbers exch get counter mul numbers 3 1 roll put
} for
} def
%/check10 - checking for 'overflow', when the number in 'numbers' is greater
% then 9, then one should add an 'overflow' to the next cell
% We are doing this after multiplication of each cells of 'numbers' by
% 'counter'.
/check10 {
0 1 MAXARRAY -2 add {/c2 exch def numbers c2 get /number exch def
numbers c2 number 10 mod put
numbers c2 1 add numbers c2 1 add get number 10 idiv add put
} for
} def
% /showar - showing an array 'numbers' in a good format
/showar
{MAXARRAY -1 add -1 0
{currentpoint pop 500 gt {crlf} if numbers exch get dup 0 ne
{/cprint 1 def Tempstr cvs show}
{cprint 0 ne {Tempstr cvs show} {pop} ifelse}
ifelse }
for} def
%------------- Main Program --------------
LM ypos moveto
/Times-Bold findfont 14 scalefont setfont
N Tempstr cvs show (!=) show
/LM 106 def
/Times-Italic findfont 14 scalefont setfont
0 1 MAXARRAY -1 add {numbers exch 0 put } for
numbers 0 1 put
1 1 N {/counter exch def mult check10 /cprint 0 def } for
showar
showpage
%%EOF
/N 1000 def
Тут у вас 1000 факториал, если что )
Да, Вы правы. Факториал 1000.
Даже посмотреть перед отправкой не удалось - последнее, что открывало PS-файлы был Gimp, который я удалил по причине не используемости. Да и форматирование в приведённом файле сбилось, видимо форматирование UNIX тому причина.
Наверное надо написать статью, почему раньше писали на PostScript. Post mortem PostScript-у, так сказать.
Потому что не было Inkscape, да? Угадал?
Угадали :-)
Посмотрел в IrfanView (после установки всех плагинов), действительно 1000! Посыпаю голову пеплом.
Да, надо писать статью - даже старожилы ( @PereslavlFoto ) уже забывают, как жилось в UNIX в 90х :-)
Мне тоже доводилось рисовать в постскрипте какие-то схемы. Очень удобная штука.
Да, и отдельный вопрос. Когда появится биткойновый майнер на постскрипте для принтера? А то PS-принтеры ещё работают, и когда они ничего не печатают, то могут заодно и майнить.
Вы лучше напишите, как ваш код работает, поразрядное умножение в десятичной системе не часто встретишь.
И почему не получится написать просто 1 1000 -1 1 { mul } for 3000 string cvs show
: даже если бы оно и смогло перемножить, надо ручками всё на строчки разбивать и каждой строчке ещё и координаты начала задавать.
Если б я помнил, без малого уже 20 лет прошло.
Но там всё было просто (студенческое переложение длинной арифметики на PostScript-e):
Число хранилось в массиве (каждая цифра в отдельном элементе). Цифры умножались в цикле и всё, что больше 9, переносилось в высшие элементы массива. О переносах
на следующую строчку заботился сам PostScript.
Да, алгоритм точно не идеальный (20 лет назад я был зелёным студентом), но работает.
Ссылка на тот файл, что у меня (привожу из-за сбитого форматирования): Тыц
Спасибо!
У меня atril прямо при просмотре/скачивании отлично обсчитал. Секунды четыре потребовалось.
1000!=40238726007709377354370243392300398571937486421071463254
379991042993851239862902059204420848696940480047998861019
719605863166687299480855890132382966994459099742450408707
375991882362772718873251977950595099527612087497546249704
360141827809464649629105639388743788648733711918104582578
364784997701247663288983595573543251318532395846307555740
911426241747434934755342864657661166779739666882029120737
914385371958824980812686783837455973174613608537953452422
158659320192809087829730843139284440328123155861103697680
135730421616874760967587134831202547858932076716913244842
623613141250878020800026168315102734182797770478463586817
016436502415369139828126481021309276124489635992870511496
497541990934222156683257208082133318611681155361583654698
404670897560290095053761647584772842188967964624494516076
535340819890138544248798495995331910172335555660213945039
973628075013783761530712776192684903435262520001588853514
733161170210396817592151090778801939317811419454525722386
554146106289218796022383897147608850627686296714667469756
291123408243920816015378088989396451826324367161676217916
890977991190375403127462228998800519544441428201218736174
599264295658174662830295557029902432415318161721046583203
678690611726015878352075151628422554026517048330422614397
428693306169089796848259012545832716822645806652676995865
268227280707578139185817888965220816434834482599326604336
766017699961283186078838615027946595513115655203609398818
061213855860030143569452722420634463179746059468257310379
008402443243846565724501440282188525247093519062092902313
649327349756551395872055965422874977401141334696271542284
586237738753823048386568897646192738381490014076731044664
025989949022222176590433990188601856652648506179970235619
389701786004081188972991831102117122984590164192106888438
712185564612496079872290851929681937238864261483965738229
112312502418664935314397013742853192664987533721894069428
143411852015801412334482801505139969429015348307764456909
907315243327828826986460278986432113908350621709500259738
986355427719674282224875758676575234422020757363056949882
508796892816275384886339690995982628095612145099487170124
451646126037902930912088908694202851064018215439945715680
594187274899809425474217358240106367740459574178516082923
013535808184009699637252423056085590370062427124341690900
4153690105933983835777939410970027753 00000000000000000
00000000000000000000000000000000000000000000000
Я открыл без проблем через Document Viewer 42.3 (Ubuntu) и там мой вариант с 472 на почтиконце. У @pharoмне кажется неверное значение.
https://planetcalc.com/8652/
1000! =
402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
PostScript не умеет на след. строчку переносить, если что. В коде для этого отдельный трюк.
Действительно, в "/crlf" происходит перенос на следующую строчку.
Ситуация и приятная (Вы разобрались в моём старом коде) и печальная (напоминает "Цветы для Элджернона").
Я ради забавы ваш код маленько подправил, лет 15 на PS не писал ) Теперь скорость зависит от N, и для 1000! скорость более чем на порядок лучше. Фишка в том, чтобы умножать не по одному разряду, а по 4 сразу, правда вылезают лишние ведущие нули.
N можно подправить в коде и хоть 3000! поставить – размер шрифта и разрядность арифметики сама подгонится.
%!PS-Adobe-2.0
%%Title: N-factorial
%%BoundingBox: 0 0 592 792
%%EndComments
% -- N --
/N 1000 def
% -------------- Variables ---------------
/LM 72 def %right margin
/RM 216 def %left margin
/ypos 720 def %current y-position
/Tempstr 8 string def
/MAXARRAY .5 N add N ln mul .918938 add N sub abs 10 ln div floor 1 add 4 div 1 add cvi def
/lineheight 19 MAXARRAY sqrt 4 div sub def
/numbers MAXARRAY array def
% ------------- Procedures ---------------
/crlf %move to next line
{ ypos lineheight sub %decrease ypos
/ypos exch def % ...& save new value
LM ypos moveto } def %move to next line
/counter 0 def% the number of current factorial because we are calculating
% it step-by-step in the loop
/c2 0 def % pointer of 'number' in array 'numbers';
% needed for adding of 'overflow' to the next cell of array
/number 0 def % current number from array 'numbers'
/cprint 0 def % necessary for printing: to not print some 'zeroes' before
% factorial
%/mult - multiplication of array 'numbers' by 'counter'
/mult
{ 0 1 MAXARRAY -1 add
{dup numbers exch get counter mul numbers 3 1 roll put
} for
} def
%/check10 - checking for 'overflow', when the number in 'numbers' is greater
% then 9999, then one should add an 'overflow' to the next cell
% We are doing this after multiplication of each cells of 'numbers' by
% 'counter'.
/check10 {
0 1 MAXARRAY -2 add {/c2 exch def numbers c2 get /number exch def
numbers c2 number 10000 mod put
numbers c2 1 add numbers c2 1 add get number 10000 idiv add put
} for
} def
/pad {
10000 add 7 string cvs 1 4 getinterval
} def
% /showar - showing an array 'numbers' in a good format
/showar
{MAXARRAY -1 add -1 0
{currentpoint pop 500 gt {crlf} if numbers exch get dup 0 ne
{/cprint 1 def pad Tempstr cvs show}
{cprint 0 ne {pad Tempstr cvs show} {pop} ifelse}
ifelse }
for} def
%------------- Main Program --------------
LM ypos moveto
/Times-Bold findfont 14 scalefont setfont
N Tempstr cvs show (!=) show
/LM 106 def
/Times-Roman findfont lineheight scalefont setfont
0 1 MAXARRAY -1 add {numbers exch 0 put } for
numbers 0 1 put
1 1 N {/counter exch def mult check10 /cprint 0 def } for
showar
showpage
%%EOF
Всем, кому интересна тема, прошу пожаловать в GitHub. Все последние коммиты - там.
Опубликован код исходной реализации языка PostScript