Differences

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

Link to this comparison view

Next revision
Previous revision
howto:calculate-dc [2010/10/12 00:36]
127.0.0.1 external edit
howto:calculate-dc [2017/01/02 08:25] (current)
gerbehar [Conditionals and Loops] typo corrected
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 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
Line 162: Line 161:
  
 The above snippet use newlines to embed comments, but it doesn'​t The above snippet use 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 that just a value, **each register is a
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 aribtrary ​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 the 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
Line 198: Line 197:
  
 Now we have several cube to calculate, we could use ''<​nowiki>​dd**</​nowiki>''​ several times, or Now we have several cube 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)
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)