Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Dc (computer program)
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
==Examples== ===Summing the entire stack=== This is implemented with a macro stored in register <code>a</code> which conditionally calls itself, performing an addition each time, until only one value remains on the stack. The <code>z</code> operator is used to push the number of entries in the stack onto the stack. The comparison operator <code>></code> pops two values off the stack in making the comparison. <syntaxhighlight lang="bash"> dc -e "1 2 4 8 16 100 0d[+z1<a]dsaxp" </syntaxhighlight> And the result is 131. ===Summing all dc expressions as lines from file=== A bare number is a valid dc expression, so this can be used to sum a file where each line contains a single number. This is again implemented with a macro stored in register <code>a</code> which conditionally calls itself, performing an addition each time, until only one value remains on the stack. <syntaxhighlight lang="bash"> dc -e "0d[?+z1<a]dsaxp" < file </syntaxhighlight> The <code>?</code> operator reads another command from the input stream. If the input line contains a decimal number, that value is added to the stack. When the input file reaches end of file, the command is null, and no value is added to the stack. <syntaxhighlight lang="bash"> { echo "5"; echo "7"; } | dc -e "0d[?+z1<a]dsaxp" </syntaxhighlight> And the result is 12. The input lines can also be complex dc commands. <syntaxhighlight lang="bash"> { echo "3 5 *"; echo "4 3 *"; echo "5dd++"; } | dc -e "0d[?+z1<a]dsaxp" </syntaxhighlight> And the result is 42. Note that since dc supports arbitrary precision, there is no concern about numeric overflow or loss of precision, no matter how many lines the input stream contains, unlike a similarly concise solution in [[AWK]]. Downsides of this solution are: the loop stops on encountering a blank line in the input stream (technically, any input line which does not add at least one numeric value to the stack); and, for handling negative numbers, leading instances of '-' to denote a negative sign must be change to '_' in the input stream, because of dc's nonstandard negative sign. The <code>?</code> operator in dc does not provide a clean way to discern reading a blank line from reading end of file. ===Unit conversion=== As an example of a relatively simple program in dc, this command (in 1 line): <syntaxhighlight lang="bash"> 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' </syntaxhighlight> converts distances from metres to feet and inches; the bulk of it is concerned with prompting for input, printing output in a suitable format and looping around to convert another number. ===Greatest common divisor=== As an example, here is an implementation of the [[Euclidean algorithm]] to find the [[Greatest common divisor|GCD]]: <syntaxhighlight lang="bash"> dc -e '??[dSarLa%d0<a]dsax+p' # shortest dc -e '[a=]P?[b=]P?[dSarLa%d0<a]dsax+[GCD:]Pp' # easier-to-read version </syntaxhighlight> ===Factorial=== Computing the [[factorial]] of an input value, <math>n! = \prod_{i=1}^n i</math> <syntaxhighlight lang="bash"> dc -e '?[q]sQ[d1=Qd1-lFx*]dsFxp' </syntaxhighlight> ===Quines in dc=== There exist also [[Quine (computing)|quines]] in the programming language dc; programs that produce its source code as output. <syntaxhighlight lang="bash"> dc -e '[91Pn[dx]93Pn]dx' dc -e '[91PP93P[dx]P]dx' </syntaxhighlight> ===Printing all prime numbers=== <syntaxhighlight lang="sh"> dc -e '2p3p[dl!d2+s!%0=@l!l^!<#]s#[s/0ds^]s@[p]s&[ddvs^3s!l#x0<&2+l.x]ds.x' </syntaxhighlight> This program was written by Michel Charpentier. It outputs the sequence of prime numbers. Note that shorter implementation is possible, which needs fourteen symbols fewer. <syntaxhighlight lang="sh"> dc -e '2p3p[pq]s$[l!2+ds!l^<$dl!%0<#]s#[+dvs^1s!l#x2l.x]ds.x' </syntaxhighlight> ===Integer factorization=== <syntaxhighlight lang="bash"> dc -e '[n=]P?[p]s2[lip/dli%0=1dvsr]s12sid2%0=13sidvsr[dli%0=1lrli2+dsi!>.]ds.xd1<2' </syntaxhighlight> This program was also written by Michel Charpentier.<ref>{{cite web |url=https://tldp.org/LDP/abs/html/mathc.html |title=Advanced Bash-Scripting Guide, Chapter 16, Example 16-52 (Factorization) |access-date=2020-09-20 }}</ref> There is a shorter <syntaxhighlight lang="bash"> dc -e "[n=]P?[lfp/dlf%0=Fdvsr]sF[dsf]sJdvsr2sf[dlf%0=Flfdd2%+1+sflr<Jd1<M]dsMx" </syntaxhighlight> and a faster solution (try with the 200-bit number {{math|2<sup>200</sup>-1}} (input <code>2 200^1-</code>) <syntaxhighlight lang="bash"> 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" </syntaxhighlight> Note that the latter can be sped up even more, if the access to a constant is replaced by a register access. <syntaxhighlight lang="bash"> 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" </syntaxhighlight> ===Calculating Pi=== An implementation of the [[Chudnovsky algorithm]] in the programming language dc. The program will print better and better approximations as it runs. But as pi is a transcendental number, the program will continue until interrupted or resource exhaustion of the machine it is run on. <syntaxhighlight lang="bash"> 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' </syntaxhighlight> A fast divide and conquer implementation of the same formula that doubles in size each iteration. It evaluates a finite number if sums as an exact rational number and only performs one large division and square root per iteration. It is fast, but will still quickly slow down as the size of the fraction increases. <syntaxhighlight lang="bash"> 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' </syntaxhighlight> ===Diffie–Hellman key exchange=== A more complex example of dc use embedded in a [[Perl]] script performs a [[Diffie–Hellman key exchange]]. This was popular as a [[signature block]] among [[cypherpunk]]s during the [[ITAR]] debates, where the short script could be run with only Perl and dc, ubiquitous programs on Unix-like operating systems:<ref>{{cite web |url=http://www.cypherspace.org/adam/rsa/perl-dh.html |title=Diffie–Hellman in 2 lines of Perl |access-date=5 Jan 2009 |author=Adam Back }}</ref> <syntaxhighlight lang="perl"> #!/usr/bin/env 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` </syntaxhighlight> A commented version is slightly easier to understand and shows how to use loops, conditionals, and the <code>q</code> command to return from a macro. With the GNU version of dc, the <code>|</code> command can be used to do arbitrary precision modular exponentiation without needing to write the X function. <syntaxhighlight lang="perl"> #!/usr/bin/env 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 '`; </syntaxhighlight> ===Environment variables=== If the [[environment variable]] DC_LINE_LENGTH exists and contains an integer that is greater than 1 and less than <math>2^{16}-1</math>, the output of number digits (according to the output base) will be restricted to this value, inserting thereafter backslashes and newlines. The default line length is 70. The special value of 0 disables line breaks.
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)