howto:calculate-dc

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Last revision Both sides next revision
howto:calculate-dc [2012/11/01 13:04]
thebonsai [Simple calculation] typo
howto:calculate-dc [2018/06/21 23:02]
izxle fixed typos and added some commas
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 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 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 thisyou 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 20output 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 modifiedthe 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. //Notewe 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 lostyou 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 +Firstlet'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 writtenit 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 operandsthe 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 ''​dc <<<​ "[f]sR 2 1 >R 1 2 >R f"''​
 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 canin factuse 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)
  • howto/calculate-dc.txt
  • Last modified: 2018/06/21 23:36
  • by izxle