Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
howto:calculate-dc [2010/10/11 22:36] 127.0.0.1 external edit |
howto:calculate-dc [2018/06/21 23:36] izxle added missing <nowiki> </nowiki> |
||
---|---|---|---|
Line 14: | Line 14: | ||
===== Simple calculation ===== | ===== Simple calculation ===== | ||
- | In brief, the //reverse polish notation// means that you first put the | + | In brief, the //reverse polish notation// means the numbers are put |
- | numbers (on a stack) and then apply an operation on these. Instead | + | on the stack first, then an operation is applied to them. Instead |
of writing ''1+1'', you write ''1 1+''. | of writing ''1+1'', you write ''1 1+''. | ||
- | By default ''dc'', unlike ''bc'', doesn't print anything, the result is just pushed on the stack. | + | By default ''dc'', unlike ''bc'', doesn't print anything, the result is pushed on the stack. |
- | You have to use to use the command "p" to print the element at the top of the stack. | + | You have to use the "p" command to print the element at the top of the stack. |
- | dc. Thus a simple operation looks like: | + | Thus a simple operation looks like: |
<code> | <code> | ||
Line 26: | Line 26: | ||
2 | 2 | ||
</code> | </code> | ||
- | I used here a "here string" present in bash 3.x, ksh93 and zsh. if your | + | I used a "here string" present in bash 3.x, ksh93 and zsh. if your |
- | shell doesn't support this you can use ''echo '1 1+p' | dc'' or if you have GNU ''dc'', you can use ''dc -e '1 1 +p'''. | + | shell doesn't support this, you can use ''echo '1 1+p' | dc'' or if you have GNU ''dc'', you can use ''dc -e '1 1 +p'''. |
Of course, you can also just run ''dc'' and enter the commands. | Of course, you can also just run ''dc'' and enter the commands. | ||
- | The classic operations are present: | + | The classic operations are: |
* addition: ''+'' | * addition: ''+'' | ||
* subtraction: ''-'' | * subtraction: ''-'' | ||
Line 47: | Line 47: | ||
</code> | </code> | ||
- | You can use the //digits// ''0'' to ''9'' and the //letters// ''A'' to ''F'' for the numbers as well as a dot (''.'') to separate the decimals. | + | You can use the //digits// ''0'' to ''9'' and the //letters// ''A'' to ''F'' as numbers, and a dot (''.'') as a decimal point. |
- | The ''A'' to ''F'' **must** be capital letters in order not to be confused with the commands that are written with lower case characters. | + | The ''A'' to ''F'' **must** be capital letters in order not to be confused with the commands specified with lower case characters. |
- | A number with a letter is considered as an hexadecimal number: | + | A number with a letter is considered hexadecimal: |
<code> | <code> | ||
dc <<< 'Ap' | dc <<< 'Ap' | ||
10 | 10 | ||
</code> | </code> | ||
- | The **output** is converted in **base 10** by default | + | The **output** is converted to **base 10** by default |
===== Scale And Base ===== | ===== Scale And Base ===== | ||
''dc'' is a calulator with abitrary precision, by default this precision is 0. | ''dc'' is a calulator with abitrary precision, by default this precision is 0. | ||
- | thus ''dc <<< "5 4/p"'' prints "1". | + | thus ''<nowiki>dc <<< "5 4/p"</nowiki>'' prints "1". |
We can increase the precision using the ''k'' command. It pops the value at the top of the stack | We can increase the precision using the ''k'' command. It pops the value at the top of the stack | ||
- | and use it as the precision: | + | and uses it as the precision argument: |
<code> | <code> | ||
dc <<< '2k5 4/p' # prints 1.25 | dc <<< '2k5 4/p' # prints 1.25 | ||
Line 70: | Line 70: | ||
324784621070388503875343276415727 | 324784621070388503875343276415727 | ||
</code> | </code> | ||
- | You can use a //very large precision//. | + | dc supports //large// precision arguments. |
You can change the base used to output (//print//) the numbers with ''o'' and the base used to | You can change the base used to output (//print//) the numbers with ''o'' and the base used to | ||
Line 76: | Line 76: | ||
<code> | <code> | ||
dc << EOF | dc << EOF | ||
- | 20 p# prints 20 output is in base 10 | + | 20 p# prints 20, output is in base 10 |
- | 16o # the output is now done in bas2 16 | + | 16o # the output is now in base 2 16 |
20p # prints 14, in hex | 20p # prints 14, in hex | ||
- | 16i # the output is now done in hex | + | 16i # the output is now in hex |
- | p # prints 14 this doesn't modify the number present in the stack | + | p # prints 14 this doesn't modify the number in the stack |
10p # prints 10 the output is done in base 16 | 10p # prints 10 the output is done in base 16 | ||
EOF | EOF | ||
</code> | </code> | ||
- | Take care that when the input value is modified the base is modified for all the commands, including ''i'': | + | Note: when the input value is modified, the base is modified for all commands, including ''i'': |
<code> | <code> | ||
Line 91: | Line 91: | ||
16i 16o # base is 16 for input and output | 16i 16o # base is 16 for input and output | ||
10p # prints 10 | 10p # prints 10 | ||
- | 10i # ! set the base to 10 in base 16 ie to 16 decimal | + | 10i # ! set the base to 10 i.e. to 16 decimal |
17p # prints 17 | 17p # prints 17 | ||
EOF | EOF | ||
</code> | </code> | ||
- | This code prints 17 while we might think that ''10i'' revert the base back to 10 and thus the number should be converted to hex and prints 11. | + | This code prints 17 while we might think that ''10i'' reverts the base back to 10 and thus the number should be converted to hex and printed as 11. |
- | The problem is that 10 was typed while the base for input was 16, thus the base was set to 10 in hexadecimal, i.e. to 16 decimal. | + | The problem is 10 was typed while the input base 16, thus the base was set to 10 hexadecimal, i.e. 16 decimal. |
<code> | <code> | ||
dc << EOF | dc << EOF | ||
16o16o10p #prints 10 | 16o16o10p #prints 10 | ||
- | Ai # set the base to A in hex ie 10 | + | Ai # set the base to A in hex i.e. 10 |
17p # prints 11 in base 16 | 17p # prints 11 in base 16 | ||
EOF | EOF | ||
Line 116: | Line 116: | ||
$ dc << EOF | $ dc << EOF | ||
2 # put 2 on the stack | 2 # put 2 on the stack | ||
- | d # duplicate ie put another 2 on the stack | + | d # duplicate i.e. put another 2 on the stack |
*p # multiply and print | *p # multiply and print | ||
c p # clear and print | c p # clear and print | ||
Line 124: | Line 124: | ||
</code> | </code> | ||
- | ''c p'' results in an error, as we would expect, as c remove everything | + | ''c p'' results in an error, as we would expect, as c removes everything |
- | on the stack. //Note how we can use ''#'' to put comments in the script.// | + | on the stack. //Note: we can use ''#'' to put comments in the script.// |
- | If you are lost you can inspect (i.e. print) the stack using the command | + | If you are lost, you can inspect (i.e. print) the stack using the command |
- | ''f''. this command does not modify the stack: | + | ''f''. The stack remains unchanged: |
<code> | <code> | ||
Line 137: | Line 137: | ||
</code> | </code> | ||
- | Note how the first element that will be poped from the stack is printed first, if you are | + | Note how the first element that will be popped from the stack is printed first, if you are |
- | used to HP calculator, it's the reverse. | + | used to an HP calculator, it's the reverse. |
- | Don't hesitate to put some ''f'' in the examples of this tutorial, it doesn't change the result | + | Don't hesitate to put ''f'' in the examples of this tutorial, it doesn't change the result, |
and it's a good way to see what's going on. | and it's a good way to see what's going on. | ||
Line 147: | Line 147: | ||
The GNU ''dc'' manual says that dc has at least **256 registers** depending on | The GNU ''dc'' manual says that dc has at least **256 registers** depending on | ||
the range of unsigned char. I'm not sure how you are supposed to use | the range of unsigned char. I'm not sure how you are supposed to use | ||
- | the NUL byte... but anyway... | + | the NUL byte. |
Using a register is easy: | Using a register is easy: | ||
Line 154: | Line 153: | ||
dc <<EOF | dc <<EOF | ||
12 # put 12 on the stack | 12 # put 12 on the stack | ||
- | sa # remove it from the stack and put (s) it in the register 'a' | + | sa # remove it from the stack (s), and put it in register 'a' |
- | 10 # now put 10 on the stack | + | 10 # put 10 on the stack |
- | la # read (l) the value of the register 'a' and push it on the stack | + | la # read (l) the value of register 'a' and push it on the stack |
+p # add the 2 values and print | +p # add the 2 values and print | ||
EOF | EOF | ||
</code> | </code> | ||
- | The above snippet use newlines to embed comments, but it doesn't | + | The above snippet uses newlines to embed comments, but it doesn't |
- | really matter, you can use ''echo '12sa10la+p'| dc'', it works the same. | + | really matter, you can use ''echo '12sa10la+p'| dc'', with the same results. |
- | The register can contain more that just a value, **each register is a | + | The register can contain more than just a value, **each register is a |
stack on its own**. | stack on its own**. | ||
Line 171: | Line 170: | ||
12sa #store 12 in 'a' | 12sa #store 12 in 'a' | ||
6Sa # with a capital S the 6 is removed | 6Sa # with a capital S the 6 is removed | ||
- | # from the main stack and pushed on the stack 'a' | + | # from the main stack and pushed on the 'a' stack |
- | lap # prints 6, the value at the top of the stack 'a' | + | lap # prints 6, the value at the top of the 'a' stack |
lap # still prints 6 | lap # still prints 6 | ||
- | Lap # prints 6 also but with a capital L, it push the value in 'a' | + | Lap # prints 6 also but with a capital L, it pushes the value in 'a' |
- | # on the main stack and pull it from the 'a' stack | + | # to the main stack and pulls it from the 'a' stack |
lap # prints 12, which is now at the top of the stack | lap # prints 12, which is now at the top of the stack | ||
EOF | EOF | ||
Line 182: | Line 181: | ||
===== Macros ===== | ===== Macros ===== | ||
- | ''dc'' let's you push aribtray strings on the stack in when put inside ''[]''. | + | ''dc'' lets you push arbitrary strings on the stack when the strings are enclosed in ''[]''. |
You can print it with ''p'': ''<nowiki>dc <<< '[Hello World!]p'</nowiki>'' and you can | You can print it with ''p'': ''<nowiki>dc <<< '[Hello World!]p'</nowiki>'' and you can | ||
evalute it with x: ''<nowiki>dc <<< '[1 2+]xp'</nowiki>''. | evalute it with x: ''<nowiki>dc <<< '[1 2+]xp'</nowiki>''. | ||
- | This is not that interesting until you combine this with registers. | + | This is not that interesting until combined with registers. |
- | First let's say we want the to calculate the square of a number | + | First, let's say we want to calculate the square of a number |
- | (don't forget to put some ''f'' in there if you are lost!): | + | (don't forget to include ''f'' if you get lost!): |
<code> | <code> | ||
dc << EOF | dc << EOF | ||
3 # push our number on the stack | 3 # push our number on the stack | ||
- | d # duplicate it ie push 3 again | + | d # duplicate it i.e. push 3 on the stack again |
d**p # duplicate again and calculate the product and print | d**p # duplicate again and calculate the product and print | ||
EOF | EOF | ||
</code> | </code> | ||
- | Now we have several cube to calculate, we could use ''<nowiki>dd**</nowiki>'' several times, or | + | Now we have several cubes to calculate, we could use ''<nowiki>dd**</nowiki>'' several times, or |
- | us a macro. | + | use a macro. |
<code> | <code> | ||
dc << EOF | dc << EOF | ||
[dd**] # push a string | [dd**] # push a string | ||
- | sa # save it in the register a | + | sa # save it in register a |
3 # push 3 on the stack | 3 # push 3 on the stack | ||
lax # push the string "dd**" on the stack and execute it | lax # push the string "dd**" on the stack and execute it | ||
p # print the result | p # print the result | ||
- | 4laxp # same thing fo 4, in one line | + | 4laxp # same operation for 4, in one line |
EOF | EOF | ||
</code> | </code> | ||
Line 216: | Line 215: | ||
it can also execute macros conditionally. ''>a'' will execute the macro | it can also execute macros conditionally. ''>a'' will execute the macro | ||
stored in the register ''a'', if the top of the stack is //greater than// the second | stored in the register ''a'', if the top of the stack is //greater than// the second | ||
- | element of the stack. Take care, that the top of the stack is the | + | element of the stack. Note: the top of the stack contains the last entry. |
- | number entered last so when written it's somehow the reverse of what | + | When written, it appears as the reverse of what we are used to reading: |
- | we are used to read: | + | |
<code> | <code> | ||
Line 228: | Line 226: | ||
</code> | </code> | ||
- | Some ''dc'' have ''>R <R =R'', GNU ''dc'' had some more, check your manual. Not | + | Some ''dc'' have ''>R <R =R'', GNU ''dc'' had some more, check your manual. Note |
- | that the test "consumes" its operands the 2 first elements are poped | + | that the test "consumes" its operands: the 2 first elements are popped |
- | off the stack (you can verify that ''dc <<< "[f]sR 2 1 >R 1 2 >R f"'' | + | off the stack (you can verify that ''<nowiki>dc <<< "[f]sR 2 1 >R 1 2 >R f"</nowiki>'' |
doesn't print anything) | doesn't print anything) | ||
Have you noticed how we can //include// a macro (string) in a macro? and as ''dc'' | Have you noticed how we can //include// a macro (string) in a macro? and as ''dc'' | ||
- | relies on a stack we can in fact use the macro recursively (have your | + | relies on a stack we can, in fact, use the macro recursively (have your |
favorite control-c key combo ready ;)) : | favorite control-c key combo ready ;)) : | ||
Line 254: | Line 252: | ||
1 - # we decrement the index by one | 1 - # we decrement the index by one | ||
si # store decremented index (i=i-1) | si # store decremented index (i=i-1) | ||
- | 0 li >L # if i > 0 the execute L | + | 0 li >L # if i > 0 then execute L |
] sL # store our macro with the name L | ] sL # store our macro with the name L | ||
Line 270: | Line 268: | ||
</code> | </code> | ||
- | I'll let you figure out the 2nd example, it's not hard, it uses the stack | + | I'll let you figure out the second example, it's not hard, it uses the stack |
instead of a register for the index. | instead of a register for the index. | ||
===== Next ===== | ===== Next ===== | ||
- | Check your dc manual, i haven't decribe everything, like the arrays | + | Check your dc manual, i haven't decribed everything, like arrays |
(only documented with "; : are used by bc(1) for array operations" on solaris, | (only documented with "; : are used by bc(1) for array operations" on solaris, | ||
probably because //echo '1 0:a 0Sa 2 0:a La 0;ap' | dc// results in | probably because //echo '1 0:a 0Sa 2 0:a La 0;ap' | dc// results in | ||
- | //Segmentation Fault (core dumped)//, the latest solaris seems to use gnu dc) | + | //Segmentation Fault (core dump) //, the latest solaris uses GNU dc) |
- | You can find some more info and dc programs there: | + | You can find more info and dc programs here: |
* [[http://en.wikipedia.org/wiki/Dc_(Unix)|http://en.wikipedia.org/wiki/Dc_(Unix)]] | * [[http://en.wikipedia.org/wiki/Dc_(Unix)|http://en.wikipedia.org/wiki/Dc_(Unix)]] | ||
- | And more example, as well as a dc implementation in python there: | + | And more example, as well as a dc implementation in python here: |
* http://en.literateprograms.org/Category:Programming_language:dc | * http://en.literateprograms.org/Category:Programming_language:dc | ||
* http://en.literateprograms.org/Desk_calculator_%28Python%29 | * http://en.literateprograms.org/Desk_calculator_%28Python%29 | ||
The manual for the 1971 dc from Bell Labs: | The manual for the 1971 dc from Bell Labs: | ||
- | * http://cm.bell-labs.com/cm/cs/who/dmr/man12.ps | + | * http://cm.bell-labs.com/cm/cs/who/dmr/man12.ps (dead link) |