Jump to content

постоянный ток (компьютерная программа)

(Перенаправлено с Dc (язык программирования) )
округ Колумбия
Оригинальный автор(ы) Лоринда Черри , Роберт Моррис
( AT&T Bell Laboratories )
Разработчик(и) Различные с открытым исходным кодом и коммерческие разработчики разработчики
Написано в Б
Операционная система Unix , Unix-подобные , Plan 9
Платформа Кросс-платформенный
Тип Команда

dc ( настольный калькулятор ) — кроссплатформенный калькулятор обратного польского языка , поддерживающий арифметику произвольной точности . [1] Его написали Лоринда Черри и Роберт Моррис из Bell Labs . [2] Это одна из старейших утилит Unix , предшествовавшая даже изобретению языка программирования C. Как и другие утилиты того времени, она обладает мощным набором функций, но кратким синтаксисом. [3] [4] Традиционно программа-калькулятор bc инфиксной записью ) реализовывалась поверх dc.

В этой статье приводятся несколько примеров в попытке дать общее представление о языке; Полный список команд и синтаксиса можно найти на странице руководства по конкретной реализации.

dc — старейшая из сохранившихся языковых программ Unix . Когда ее родная лаборатория Bell Labs получила PDP-11 , dc, написанный на B , стал первым языком, который можно было запустить на новом компьютере, еще до появления ассемблера. [2] Кен Томпсон высказал мнение, что dc была самой первой программой, написанной на машине. [5]

Основные операции

[ редактировать ]

Чтобы умножить четыре и пять в постоянном токе (обратите внимание, что большая часть пробелов необязательна):

$ cat << EOF > cal.txt
4 5 *
p
EOF

$ dc cal.txt
20
$

Результаты также доступны по командам:

$ echo "4 5 * p" | dc

или

$ dc -
4 5*pq
20

$ dc
4 5 *
p
20
q

$ dc -e '4 5 * p'

Это переводится как «поместите четыре и пять в стек, затем с помощью оператора умножения извлеките два элемента из стека, умножьте их и поместите результат в стек». Тогда p Команда используется для проверки (вывода на экран) верхнего элемента стека. q команда завершает вызванный экземпляр dc. Обратите внимание, что числа должны находиться на расстоянии друг от друга, хотя некоторые операторы в этом нет необходимости.

Арифметическая точность изменяется командой k, который устанавливает количество дробных цифр (количество цифр после точки ), которые будут использоваться для арифметических операций. Поскольку точность по умолчанию равна нулю, эта последовательность команд выдает 0 как результат:

2 3 / p

Регулируя точность с помощью k, можно получить произвольное количество десятичных знаков. Эта последовательность команд выводит .66666.

5 k
2 3 / p

Чтобы оценить : ( v вычисляет квадратный корень из вершины стека и _ используется для ввода отрицательного числа):

12 _3 4 ^ + 11 / v 22 -
p

Чтобы поменять местами два верхних элемента стека, используйте команду r команда. Чтобы дублировать верхний элемент, используйте d команда.

Ввод/вывод

[ редактировать ]

Чтобы прочитать строку из стандартного ввода , используйте команду ? команда. При этом строка оценивается так, как если бы это была команда постоянного тока, поэтому необходимо, чтобы она была синтаксически правильной и представляла потенциальную проблему безопасности, поскольку ! Команда dc позволяет выполнять произвольную команду.

Как упоминалось выше, p печатает верхнюю часть стека с новой строкой после нее. n извлекает верхнюю часть стека и печатает ее без завершающего символа новой строки. f печатает весь стек, по одной записи в строке.

dc также поддерживает произвольные входные и выходные системы счисления . i Команда извлекает вершину стека и использует ее в качестве базы ввода. Шестнадцатеричные цифры должны быть в верхнем регистре, чтобы избежать конфликтов с командами постоянного тока, и ограничиваются AF. o Команда делает то же самое для выходной базы, но имейте в виду, что входная база влияет на последующий анализ каждого числового значения, поэтому обычно рекомендуется сначала установить выходную базу. Поэтому 10o устанавливает выходное основание системы счисления равным текущему входному основанию системы счисления, но обычно не равному 10 (десяти). Тем не менее Ao сбрасывает выходную базу до 10 (десяти), независимо от входной базы. Чтобы прочитать значения, K, I и O команды помещают текущую точность, входное и выходное основание системы счисления на вершину стека.

Например, для преобразования шестнадцатеричного формата в двоичный:

$ echo 16i2o DEADBEEFp | dc
11011110101011011011111011101111

Особенности языка

[ редактировать ]

Регистры

[ редактировать ]

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

Механизмом, лежащим в основе макросов и условий, является регистр , который в dc представляет собой место хранения с односимвольным именем, которое можно сохранять и извлекать из: sc извлекает вершину стека и сохраняет ее в регистре c, и lc помещает значение регистра c в стек. Например:

3 sc 4 lc * p

Регистры также можно рассматривать как вторичные стеки, поэтому значения можно перемещать между ними и основным стеком с помощью S и L команды.

Строковые значения заключаются в [ и ] символы и могут быть помещены в стек и сохранены в регистрах. a Команда преобразует младший байт числового значения в символ ASCII или, если верхняя часть стека является строкой, заменяет ее первым символом строки. Не существует других способов создания строк или выполнения манипуляций со строками, кроме как выполнить их с помощью x команду или распечатать ее с помощью P команда.

The # символ начинает комментарий до конца строки.

Затем реализуются макросы, позволяющие регистрам и записям стека быть не только числами, но и строками. Строку можно вывести на печать, но ее также можно выполнить (т.е. обработать как последовательность команд постоянного тока). Например, мы можем сохранить макрос, чтобы добавить единицу, а затем умножить ее на 2 в регистр m:

[1 + 2 *] sm

а затем (с помощью x команда, которая выполняет вершину стека), мы можем использовать ее следующим образом:

3 lm x p

Условные предложения

[ редактировать ]

Наконец, мы можем использовать этот макромеханизм для предоставления условий. Команда =r извлекает два значения из стека и выполняет макрос, хранящийся в регистре r только если они равны. Итак, это печатает строку equal только если два верхних значения в стеке имеют одинаковое значение:

[[equal]p] sm 5 5 =m

Другие условные обозначения >, !>, <, !<, !=, которые выполняют указанный макрос, если два верхних значения в стеке больше, меньше или равны («не больше»), меньше, больше или равны («не меньше») и не равны соответственно . Обратите внимание, что порядок операндов при сравнении неравенств противоположен порядку в арифметике; 5 3 - оценивается как 5 - 3 = 2, но 5 3 <t запускает содержимое t зарегистрироваться, потому что 3 < 5.

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

# F(x): return x!
# if x-1 > 1
#     return x * F(x-1)
# otherwise
#     return x
[d1-d1<F*]dsFxp

The 1Q команда выходит из макроса, позволяя вернуться раньше. q завершает работу с двух уровней макросов (и самого dc, если в стеке вызовов меньше двух уровней). z помещает текущую глубину стека перед z операция.

Суммируем весь стек

[ редактировать ]

Это реализуется с помощью макроса, хранящегося в реестре. a который условно вызывает сам себя, каждый раз выполняя сложение, пока в стеке не останется только одно значение. z Оператор используется для помещения количества записей из стека в стек. Оператор сравнения > извлекает два значения из стека при сравнении.

dc -e "1 2 4 8 16 100 0d[+z1<a]dsaxp"

И результат 131.

Суммирование всех выражений постоянного тока в виде строк из файла

[ редактировать ]

Простое число является допустимым выражением постоянного тока, поэтому его можно использовать для суммирования файла, в котором каждая строка содержит одно число.

Это снова реализовано с помощью макроса, хранящегося в регистре. a который условно вызывает сам себя, каждый раз выполняя сложение, пока в стеке не останется только одно значение.

cat file | dc -e "0d[?+z1<a]dsaxp"

The ? оператор считывает другую команду из входного потока. Если строка ввода содержит десятичное число, это значение добавляется в стек. Когда входной файл достигает конца файла, команда становится нулевой, и в стек не добавляется никакое значение.

{ echo "5"; echo "7"; } | dc -e "0d[?+z1<a]dsaxp"

И результат 12.

Входные строки также могут представлять собой сложные команды постоянного тока.

{ echo "3 5 *"; echo "4 3 *"; echo "5dd++"; } | dc -e "0d[?+z1<a]dsaxp"

И результат 42.

Обратите внимание: поскольку dc поддерживает произвольную точность, не возникает проблем с числовым переполнением или потерей точности, независимо от того, сколько строк содержит входной поток, в отличие от аналогичного лаконичного решения в AWK .

Недостатками этого решения являются: цикл останавливается при обнаружении пустой строки во входном потоке (технически это любая строка ввода, которая не добавляет хотя бы одно числовое значение в стек); а для обработки отрицательных чисел ведущие экземпляры '-' для обозначения отрицательного знака должны быть заменены на '_' во входном потоке из-за нестандартного отрицательного знака dc. ? Оператор в dc не обеспечивает четкого способа отличить чтение пустой строки от чтения конца файла.

Преобразование единиц измерения

[ редактировать ]

В качестве примера относительно простой программы на dc, эта команда (в 1 строку):

dc -e '[[Enter a number (metres), or 0 to exit]PAP]sh[q]sz[lhx?d0=zAk.0254/.5+0kC~1/rn[ feet ]Pn[ inches]PAPdx]dx'

конвертирует расстояния из метров в футы и дюймы; большая часть его связана с запросом ввода, выводом вывода в подходящем формате и циклическим преобразованием другого числа.

Наибольший общий делитель

[ редактировать ]

В качестве примера, вот реализация алгоритма Евклида для поиска НОД :

dc -e '??[dSarLa%d0<a]dsax+p'                  # shortest
dc -e '[a=]P?[b=]P?[dSarLa%d0<a]dsax+[GCD:]Pp' # easier-to-read version

Факториал

[ редактировать ]

Вычисление факториала входного значения,

dc -e '?[q]sQ[d1=Qd1-lFx*]dsFxp'

Какие в Вашингтоне

[ редактировать ]

существуют также куайны В языке программирования dc ; программы, которые создают исходный код в качестве вывода.

dc -e '[91Pn[dx]93Pn]dx'

dc -e '[91PP93P[dx]P]dx'

Печать всех простых чисел

[ редактировать ]
echo '2p3p[dl!d2+s!%0=@l!l^!<#]s#[s/0ds^]s@[p]s&[ddvs^3s!l#x0<&2+l.x]ds.x' | dc

Эту программу написал Мишель Шарпантье. Он выводит последовательность простых чисел. Обратите внимание, что возможна более короткая реализация, которая читает на четырнадцать символов меньше.

echo '2p3p[pq]s$[l!2+ds!l^<$dl!%0<#]s#[+dvs^1s!l#x2l.x]ds.x' | dc

Целочисленная факторизация

[ редактировать ]
dc -e '[n=]P?[p]s2[lip/dli%0=1dvsr]s12sid2%0=13sidvsr[dli%0=1lrli2+dsi!>.]ds.xd1<2'

Эту программу также написал Мишель Шарпантье. [6]

Есть более короткий

dc -e "[n=]P?[lfp/dlf%0=Fdvsr]sF[dsf]sJdvsr2sf[dlf%0=Flfdd2%+1+sflr<Jd1<M]dsMx"

и более быстрое решение (попробуйте с 200-битным номером 2 200 -1 (вход 2 200^1-)

dc -e "[n=]P?[lfp/dlf% 0=Fdvsr]sFdvsr2sfd2%0=F3sfd3%0=F5sf[dlf%0=Flfd4+sflr>M]sN[dlf%0=Flfd2+sflr>N]dsMx[p]sMd1<M"

Обратите внимание, что последнее можно ускорить еще больше, если доступ к константе заменить доступом к регистру.

dc -e "[n=]P?[lfp/dlf%l0=Fdvsr]sF2s2dvsr2sf4s4d2%0=F3sfd3%0=F5sf[dlf%l0=Flfdl4+sflr>M]sN[dlf%l0=Flfdl2+sflr>N]dsMx[p]sMd1<M"

Вычисление Пи

[ редактировать ]

Реализация алгоритма Чудновского на языке программирования dc. По мере работы программа будет печатать все лучшие и лучшие приближения. Но поскольку число «пи» является трансцендентным, программа будет продолжать работу до тех пор, пока не будет прервана или пока не исчерпаются ресурсы машины, на которой она выполняется.

dc -e '_640320[0ksslk3^16lkd12+sk*-lm*lhd1+sh3^/smlxlj*sxll545140134+dsllm*lxlnk/ls+dls!=P]sP3^sj7sn[6sk1ddshsxsm13591409dsllPx10005v426880*ls/K3-k1/pcln14+snlMx]dsMx'

Быстрая реализация той же формулы «разделяй и властвуй», размер которой удваивается на каждой итерации. Он вычисляет конечное число, если суммирует его как точное рациональное число и выполняет только одно большое деление и извлечение квадратного корня за итерацию. Он быстрый, но все равно быстро замедляется по мере увеличения размера фракции.

dc -e '1Sk1SR13591409dSBSP426880dSQ4/3^9*SC[0r-]s-[lkE*1-k10005vlQ*lP/nAan0k]dSox[Lkd1+Skdd1+Sk3^lC*SQ2*1-d3*d*4-*dSR545140134LB+dSB*lk2%0=-SP]dszx[LRLRdLP*LPLQdLQ*SQ*+SP*SR]sc[d1-d0<yd0<yd0=z0=zlcx]sy0[lcxlox1+lyxllx]dslx'

Обмен ключами Диффи-Хеллмана

[ редактировать ]

Более сложный пример использования постоянного тока, встроенный в сценарий Perl , выполняет обмен ключами Диффи-Хеллмана . Это было популярно в качестве сигнатурного блока среди шифропанков во время дебатов в ITAR , где короткий сценарий можно было запустить только с помощью Perl и dc, вездесущих программ в Unix-подобных операционных системах: [7]

#!/usr/bin/perl -- -export-a-crypto-system-sig Diffie-Hellman-2-lines
($g, $e, $m) = @ARGV, $m || die "$0 gen exp mod\n";
print `echo "16dio1[d2%Sa2/d0<X+d*La1=z\U$m%0]SX$e"[$g*]\EszlXx+p | dc`

Версия с комментариями немного проще для понимания и показывает, как использовать циклы, условные выражения и q команда возврата из макроса. В версии dc для GNU | Эту команду можно использовать для возведения в степень модульной степени произвольной точности без необходимости написания функции X.

#!/usr/bin/perl

my ($g, $e, $m) = map { "\U$_" } @ARGV;
die "$0 gen exp mod\n" unless $m;

print `echo $g $e $m | dc -e '
# Hex input and output
16dio
# Read m, e and g from stdin on one line
?SmSeSg

# Function z: return g * top of stack
[lg*]sz

# Function Q: remove the top of the stack and return 1
[sb1q]sQ

# Function X(e): recursively compute g^e % m
# It is the same as Sm^Lm%, but handles arbitrarily large exponents.
# Stack at entry: e
# Stack at exit: g^e % m
# Since e may be very large, this uses the property that g^e % m == 
#     if( e == 0 )
#         return 1
#     x = (g^(e/2)) ^ 2
#     if( e % 2 == 1 )
#         x *= g
#     return x %
[
    d 0=Q   # return 1 if e==0 (otherwise, stack: e)
    d 2% Sa # Store e%2 in a (stack: e)
    2/      # compute e/2
    lXx     # call X(e/2)
    d*      # compute X(e/2)^2
    La1=z   # multiply by g if e%2==1
    lm %    # compute (g^e) % m
] SX

le          # Load e from the register
lXx         # compute g^e % m
p           # Print the result
'`;

Переменные среды

[ редактировать ]

Если переменная среды DC_LINE_LENGTH существует и содержит целое число больше 1 и меньше , вывод цифр числа (в соответствии с базой вывода) будет ограничен этим значением, после чего будут вставлены обратные косые черты и символы новой строки. Длина строки по умолчанию равна 70. Специальное значение 0 отключает разрывы строк.

См. также

[ редактировать ]
  1. ^ dc(1): калькулятор произвольной точности – Linux пользователя по командам Руководство
  2. ^ Jump up to: а б Макилрой, доктор медицины (1987). Читатель Research Unix: аннотированные выдержки из Руководства программиста, 1971–1986 (PDF) (Технический отчет). CSTR. Лаборатории Белла. 139.
  3. ^ «Источники страницы руководства для 7-го издания Unix dc» . Архивировано из оригинала 23 августа 2004 г. Проверено 23 июня 2004 г.
  4. ^ Ричи, Деннис М. (сентябрь 1979 г.). «Эволюция системы разделения времени Unix» . Архивировано из оригинала 6 мая 2010 г.
  5. ^ Брайан Керниган и Кен Томпсон. Невероятное удовольствие для любого участника Vintage Computer Fest 2019: Керниган берет интервью у Томпсона о Unix . Ютуб. Событие происходит в 29:45 . Проверено 3 сентября 2019 г.
  6. ^ «Расширенное руководство по написанию сценариев Bash, глава 16, пример 16-52 (факторизация)» . Проверено 20 сентября 2020 г.
  7. ^ Адам Бэк. «Диффи-Хеллман в 2 строках Perl» . Проверено 5 января 2009 г.
[ редактировать ]


Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 46e052f373df8c79361dc12b0f9fd749__1702140000
URL1:https://arc.ask3.ru/arc/aa/46/49/46e052f373df8c79361dc12b0f9fd749.html
Заголовок, (Title) документа по адресу, URL1:
dc (computer program) - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)