432 lines
14 KiB
Org Mode
432 lines
14 KiB
Org Mode
#+TITLE: calc examples
|
|
# #+DATE: <2013-08-09 Fri>
|
|
#+AUTHOR: Derek Feichtinger
|
|
#+EMAIL: derek.feichtinger@psi.ch
|
|
#+OPTIONS: ':nil *:t -:t ::t <:t H:3 \n:nil ^:t arch:headline
|
|
#+OPTIONS: author:t c:nil creator:comment d:(not LOGBOOK) date:t e:t
|
|
#+OPTIONS: email:nil f:t inline:t num:t p:nil pri:nil stat:t tags:t
|
|
#+OPTIONS: tasks:t tex:t timestamp:t toc:t todo:t |:t
|
|
#+CREATOR: Emacs 24.3.1 (Org mode 8.0.7)
|
|
#+DESCRIPTION:
|
|
#+EXCLUDE_TAGS: noexport
|
|
#+KEYWORDS:
|
|
#+LANGUAGE: en
|
|
#+SELECT_TAGS: export
|
|
|
|
# By default I do not want that source code blocks are evaluated on export. Usually
|
|
# I want to evaluate them interactively and retain the original results.
|
|
#+PROPERTY: header-args :eval never-export
|
|
|
|
* Version information
|
|
#+BEGIN_SRC emacs-lisp :results output :exports both
|
|
(princ (concat (format "Emacs version: %s\n" (emacs-version))
|
|
(format "org version: %s\n" (org-version))))
|
|
|
|
#+END_SRC
|
|
|
|
#+RESULTS:
|
|
: Emacs version: GNU Emacs 26.2 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.22.30)
|
|
: of 2019-04-14
|
|
: org version: 9.3.7
|
|
|
|
* General
|
|
- refer to the [[info:calc#Top][Calc info pages]]
|
|
- Note that, unlike in usual computer notation, multiplication binds
|
|
more strongly than division: `a*b/c*d' is equivalent to
|
|
`(a*b)/(c*d)'
|
|
- [[https://github.com/SueDNymme/emacs-calc-qref][Nice reference sheet]] on calc maintained by Sue D. Nymme
|
|
|
|
* babel Calc
|
|
|
|
Not too useful, yet. Embedded calc certainly is better for
|
|
inlining math in documents. Using Elisp to directly interacting with
|
|
calc also is more powerful.
|
|
|
|
#+BEGIN_SRC calc
|
|
24
|
|
3
|
|
'/
|
|
#+END_SRC
|
|
|
|
#+RESULTS:
|
|
: 8
|
|
|
|
|
|
- solving an equation
|
|
#+BEGIN_SRC calc :exports both
|
|
fsolve(x*2+x=4,x)
|
|
#+END_SRC
|
|
|
|
#+RESULTS:
|
|
: x = 1.33333333333
|
|
|
|
|
|
- solving a linear system of equations
|
|
#+BEGIN_SRC calc
|
|
fsolve([x + y = a, x - y = b],[x,y])
|
|
#+END_SRC
|
|
|
|
#+RESULTS:
|
|
: [x = a + (b - a) / 2, y = (a - b) / 2]
|
|
|
|
* Calc from lisp
|
|
- [[info:calc#Calling%20Calc%20from%20Your%20Programs][Emacs Info Manual: Calling Calc from your programs]]
|
|
- nice blog post on [[http://nullprogram.com/blog/2015/10/30/][RSA cryptography using emacs Calc]] by Chris
|
|
Wellons on his [[http://nullprogram.com/][nullprogram]] blog. Contains examples on =calc-eval=
|
|
usage.
|
|
|
|
** basic use of calc-eval
|
|
The variables in formulas are replaced by the additional arguments. Arguments can be given as string or number.
|
|
#+BEGIN_SRC emacs-lisp :results output
|
|
(print (calc-eval "2^$1 - 1 + $2" nil 3 5))
|
|
(print (calc-eval "2^$1 - 1" nil 128))
|
|
|
|
(print (calc-eval "$1 < $2" 'pred "4000" "5000"))
|
|
(print (calc-eval "$1 > $2" 'pred "4000" "5000"))
|
|
(print (calc-eval "$1 < $2" nil "4000" "5000"))
|
|
(print (calc-eval "$1 > $2" nil "4000" "5000"))
|
|
(print (calc-eval "nextprime($1)" nil "100000000000000000"))
|
|
|
|
;; radix can be chosen by separating radix by # from number
|
|
(print (calc-eval "16#deadbeef"))
|
|
(print (calc-eval "2#1111"))
|
|
#+END_SRC
|
|
|
|
#+RESULTS:
|
|
#+begin_example
|
|
|
|
"12"
|
|
|
|
"340282366920938463463374607431768211455"
|
|
|
|
t
|
|
|
|
nil
|
|
|
|
"1"
|
|
|
|
"0"
|
|
|
|
"100000000000000003"
|
|
|
|
"3735928559"
|
|
|
|
"15"
|
|
#+end_example
|
|
|
|
The second argument serves as a separator if the result is a list of expressions. By default the list
|
|
is printed comma-separated.
|
|
#+BEGIN_SRC emacs-lisp :results output
|
|
(print (calc-eval "10+5, 7*3, 5/2"))
|
|
(print (calc-eval "10+5, 7*3, 5/2" ";"))
|
|
(print (calc-eval "10+5, 7*3, 5/2" "___"))
|
|
#+END_SRC
|
|
|
|
#+RESULTS:
|
|
:
|
|
: "15, 21, 2.5"
|
|
:
|
|
: "15;21;2.5"
|
|
:
|
|
: "15___21___2.5"
|
|
|
|
** using calc-eval to supply raw calc objects as input to calc internal functions
|
|
|
|
calc internal functions deal with /raw/ calc objects. These can also be obtained through =calc-eval= by
|
|
passing the =raw= as the second argument.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(calc-eval (math-convert-units (calc-eval "10 m" 'raw)
|
|
(calc-eval "ft" 'raw)))
|
|
#+END_SRC
|
|
|
|
#+RESULTS:
|
|
: 32.8083989501 ft
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(calc-eval (math-simplify-units (calc-eval "10 m + 1 mm" 'raw)))
|
|
#+END_SRC
|
|
|
|
#+RESULTS:
|
|
: 10.001 m
|
|
|
|
Todo: I do not know how the second arg to math-to-standard-units is used. Nil
|
|
works as well as any other list, it seems.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(calc-eval
|
|
(math-to-standard-units
|
|
(calc-eval "5 J" 'raw) nil))
|
|
#+END_SRC
|
|
|
|
#+RESULTS:
|
|
: 5000 g m^2 / s^2
|
|
|
|
** math-read-exprs returns the AST of an expression
|
|
|
|
To understand the lisp expressions that will get executed to obtain
|
|
a result, one can use the =math-read-exprs= function. It returns an
|
|
AST of the expression.
|
|
|
|
|
|
#+BEGIN_SRC emacs-lisp :results verbatim
|
|
(math-read-exprs "5 * 6 - 20")
|
|
#+END_SRC
|
|
|
|
#+RESULTS:
|
|
: ((- (* 5 6) 20))
|
|
|
|
#+BEGIN_SRC emacs-lisp :results verbatim
|
|
(math-read-exprs "x=vsum(1, 2, 3)")
|
|
#+END_SRC
|
|
|
|
#+RESULTS:
|
|
: ((calcFunc-eq (var x var-x) (calcFunc-vsum 1 2 3)))
|
|
|
|
Lets try executing the lisp (note that the result is enclosed by an
|
|
extra parentheses).
|
|
#+begin_src elisp :results verbatim
|
|
(calcFunc-eq '(var x var-x) (calcFunc-vsum 1 2 3))
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
: (calcFunc-eq (var x var-x) 6)
|
|
|
|
#+begin_src elisp :results verbatim
|
|
(calc-eval (calcFunc-eq '(var x var-x) (calcFunc-vsum 1 2 3)))
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
: "x = 6"
|
|
|
|
** Stack operations: push, pop and top
|
|
|
|
- =push= pushes the element onto the stack
|
|
- =pop= deletes as many elements from the stack as the preceding integer argument indicates
|
|
- =0 pop= is convenient for finding out the size of the stack
|
|
- =top= retrieves the value at the indicated position of the stack
|
|
#+BEGIN_SRC emacs-lisp :results output :exports both
|
|
(princ (format "Size of the stack: %s\n" (calc-eval 0 'pop)))
|
|
(calc-eval "10 ft" 'push)
|
|
(calc-eval "20 ft" 'push)
|
|
(calc-eval "30 ft" 'push)
|
|
(princ (format "After 3*push: Size of the stack: %s (top element: %s)\n"
|
|
(calc-eval 0 'pop)
|
|
(calc-eval 1 'top)))
|
|
(princ (format "element on second level of stack: %s\n" (calc-eval 2 'top)))
|
|
(calc-eval 2 'pop)
|
|
(princ (format "After 3*push: Size of the stack: %s (top element: %s)\n"
|
|
(calc-eval 0 'pop)
|
|
(calc-eval 1 'top)))
|
|
(calc-eval 1 'pop)
|
|
#+END_SRC
|
|
|
|
#+RESULTS:
|
|
: Size of the stack: 5
|
|
: After 3*push: Size of the stack: 8 (top element: 30 ft)
|
|
: element on second level of stack: 20 ft
|
|
: After 3*push: Size of the stack: 6 (top element: 10 ft)
|
|
|
|
** executing functions on the stack
|
|
#+BEGIN_SRC emacs-lisp :results output :exports both
|
|
(calc-eval "10 ft" 'push)
|
|
(calc-base-units)
|
|
;; retrieve the value from the stack as a string. Note that it still stays on the stack!
|
|
(print (calc-eval 1 'top))
|
|
;; clean the value from the stack
|
|
(calc-eval 1 'pop)
|
|
#+END_SRC
|
|
|
|
#+RESULTS:
|
|
:
|
|
: "3.048 m"
|
|
|
|
|
|
It is also possible to execute Calc keyboard macros, i.e. the string is interpreted as
|
|
interactive keyboard strokes in calc mode.
|
|
#+BEGIN_SRC emacs-lisp :results output :exports both
|
|
(calc-eval "10 ft" 'push)
|
|
;; calc keys for base unit conversion
|
|
(calc-eval "ub" 'macro)
|
|
(print (calc-eval 1 'top))
|
|
;; pop one item from stack
|
|
(calc-eval "\C-d" 'macro)
|
|
#+END_SRC
|
|
|
|
#+RESULTS:
|
|
:
|
|
: "3.048 m"
|
|
|
|
** Some other examples of using calc in lisp
|
|
|
|
#+BEGIN_SRC emacs-lisp :results output
|
|
(princ
|
|
(format "%s %s"
|
|
(calc-eval "deg(37@ 26' 36.42)")
|
|
;; now using pure lisp
|
|
(math-format-number
|
|
(calcFunc-deg '(hms 37 26 (float 3642 -2))))))
|
|
#+END_SRC
|
|
|
|
#+RESULTS:
|
|
: 37.44345 37.44345
|
|
|
|
* Org configurations for Calc
|
|
- https://emacs.stackexchange.com/questions/59179/specify-precision-using-calc-in-org-mode-spreadsheets/59181#59181
|
|
The variable org-calc-default-modes is used to customize Calc for org usage
|
|
#+begin_src elisp
|
|
(defcustom org-calc-default-modes
|
|
'(calc-internal-prec 12
|
|
calc-float-format (float 8)
|
|
calc-angle-mode deg
|
|
calc-prefer-frac nil
|
|
calc-symbolic-mode nil
|
|
calc-date-format (YYYY "-" MM "-" DD " " Www (" " hh ":" mm))
|
|
calc-display-working-message t)
|
|
"List with Calc mode settings for use in `calc-eval' for table formulas.
|
|
The list must contain alternating symbols (Calc modes variables and values).
|
|
Don't remove any of the default settings, just change the values. Org mode
|
|
relies on the variables to be present in the list."
|
|
:group 'org-table-calculation
|
|
:type 'plist)
|
|
#+end_src
|
|
|
|
* Calc usage in tables
|
|
** Unit conversions by defining new functions with defmath
|
|
- from http://article.gmane.org/gmane.emacs.orgmode/93489
|
|
|
|
Displaying all calc units in a buffer can be obtained by executing
|
|
#+BEGIN_SRC emacs-lisp :exports source
|
|
(calc-view-units-table 1)
|
|
#+END_SRC
|
|
|
|
Calc preserves units and variables in table operations.
|
|
|
|
| distance | time | speed |
|
|
|----------+--------+-------------|
|
|
| 3 km | 2.5 hr | 1.2 km / hr |
|
|
#+TBLFM: @2$3=$1/$2
|
|
|
|
|
|
| speed | simplified speed |
|
|
|--------------+------------------|
|
|
| 40km / 2.5hr | 16. km / hr |
|
|
#+TBLFM: @2$2=usimplify($1)
|
|
|
|
We can also decide to use calc via its elisp api. To understand
|
|
the following lisp formula that involves calc internal functions
|
|
q.v. the [[Calc from lisp]] section.
|
|
|
|
| km | ft |
|
|
|-------+---------|
|
|
| 2.5km | 8202.10 |
|
|
#+TBLFM: $2='(calc-eval (math-convert-units (calc-eval $1 'raw) (calc-eval "ft" 'raw))); %.2f
|
|
|
|
Defining a new calc function for unit conversion with defmath
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defmath uconv (expr target-units &optional pure)
|
|
(math-convert-units expr target-units pure))
|
|
#+END_SRC
|
|
|
|
#+RESULTS:
|
|
: calcFunc-uconv
|
|
|
|
| km | ft |
|
|
|--------+--------------|
|
|
| 2.5 km | 8202.0997 ft |
|
|
#+TBLFM: $2=uconv($1, ft)
|
|
|
|
Using the units from the table header (if the 3rd arg is given to
|
|
uconv, the output is stripped of the unit):
|
|
|
|
| km | ft |
|
|
|-----+-----------|
|
|
| 2.5 | 8202.0997 |
|
|
#+TBLFM: $2 = uconv($1 * @<$1, @<$2, t)
|
|
|
|
The standard calc function usimplify also works for this use
|
|
case:
|
|
|
|
| km | ft |
|
|
|-----+-----------|
|
|
| 2.5 | 8202.0997 |
|
|
#+TBLFM: $2 = usimplify($1 * @<$1 / @<$2)
|
|
|
|
A lisp equivalent of the above
|
|
#+begin_src elisp
|
|
(calc-eval "usimplify(2.5 km / ft)")
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
: 8202.09973753
|
|
|
|
Let's define a function that converts to base units
|
|
#+begin_src elisp
|
|
(defmath ustd (expr) (math-simplify-units (math-to-standard-units expr nil)))
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
: calcFunc-ustd
|
|
|
|
| distance | time | speed | std unit speed | speed in ft/s |
|
|
|----------+--------+-------------+------------------+------------------|
|
|
| 3 km | 2.5 hr | 1.2 km / hr | 0.33333333 m / s | 1.0936133 ft / s |
|
|
#+TBLFM: @2$3=$1/$2::@2$4=ustd($3)::@2$5=uconv($-1, ft/s)
|
|
|
|
* Some standard Calc functions that can be used in formulas
|
|
- [[info:calc#Formulas]]
|
|
- factorial: $6! => 720 $ also fact(6) can be used in writing
|
|
- find: $ find([5, 6, 7, 8], 6) => 2 $
|
|
- power: $pow(2, 3) => 8 $ $2^3 => 8 $
|
|
- modulo: $mod(10, 3) => 1$ $10 % 3 => 1 $
|
|
- binomial coefficient: $choose(3, 2) => 3$
|
|
- random numbers: $random(10) => 7$
|
|
- binomial distribution: the result (`utpb(x,n,p)') is the
|
|
probability that an event will occur X or more times out of N
|
|
trials, if its probability of occurring in any given trial is P:
|
|
$utpb(2, 6, 1/6) => 0.263224451304$
|
|
- gaussian distribution with mean m and stdev s. Probability that a normal
|
|
distributed random variable will exceed x: uttn(x,m,s):
|
|
$utpn(0.2b, 0, 0.5) => 0.34457825839$
|
|
- http://www-zeuthen.desy.de/~kolanosk/smd_ss02/skripte/
|
|
- prime factorisation $ prfac(9370) => [2, 5, 937] $
|
|
|
|
** Time calculations
|
|
q.v. [[info:calc#Date%20Arithmetic][info:calc#Date Arithmetic]]
|
|
|
|
- $now(0) => <11:03:18pm Sun Aug 11, 2013>$
|
|
- $now() => <10:48:31pm Wed Jun 28, 2017> $
|
|
- Using calc HMS forms
|
|
- $ 11@ 41' 15.561" - 11@ 40' 58.096" => 0@ 0' 17.465" $
|
|
- The date function with a date form as argument returns a number of days since Jan 1, 1 AD.
|
|
The date function with an INT argument yields back a date form.
|
|
- $date(<Sun Aug 11, 2013>) => 735091 $
|
|
- $date(735091) => <Sun Aug 11, 2013> $
|
|
- $date(<10:00am Sun Aug 11, 2013>) => 735091.416667 $
|
|
- $date(<Sun Aug 11, 2013>) - date(<Thu Aug 1, 2013>) => 10 $
|
|
- $<Sun Aug 11, 2013> - <Thu Aug 1, 2013> => 10 $
|
|
- $date(<10:00am Sun Aug 11, 2013>) - date(<9:00am Thu Aug 1, 2013>) => 10.041667 $
|
|
- The date function with a comma separated list builds a date or a date/time form
|
|
- $date(2017, 6, 26) => <Mon Jun 26, 2017> $
|
|
- $date(2017, 6, 26, 11@ 41' 15.561") => <11:41:16am Mon Jun 26, 2017> $
|
|
- $date(2017, 6, 26, 11, 41, 15) => <11:41:15am Mon Jun 26, 2017> $
|
|
- Not quite clear whether the angular bracket format is any good for more exact calculations
|
|
- $ <11:03:18pm Sun Aug 11, 2013> - <11:03:18pm Sun Aug 11, 2013> => 0. $
|
|
- $ <11:03:18pm Sun Aug 11, 2013> - <11:02:18pm Sun Aug 11, 2013> => 6.94e-4 $
|
|
- $ <11:03:18pm Sun Aug 11, 2013> - <11:03:17pm Sun Aug 11, 2013> => 1.2e-5 $
|
|
- $ <11:03:18pm Sun Aug 11, 2013> - <6:03:18pm Sun Aug 11, 2013> => 0.208333 $
|
|
- Unix time
|
|
- $unixtime(<9:00am Wed Jun 28, 2017>) => 1498640400 $
|
|
- $unixtime(1498640400) => <9:00am Wed Jun 28, 2017> $
|
|
- $unixtime(now(0)) => 1376262280$
|
|
- Julian date
|
|
- $julian(date(2017, 6, 26)) => 2457929 $
|
|
- $julian(2457929) => <Mon Jun 26, 2017> $
|
|
- Using a calc variable
|
|
- $ testdate := <11:41:15am Mon Jun 26, 2017> $
|
|
- $ year(testdate) => 2017 $
|
|
|
|
$ date(date(<Fri Apr 16, 2010>) - 10) => <Tue Apr 6, 2010> $
|
|
|
|
* COMMENT babel settings
|
|
Local variables:
|
|
org-confirm-babel-evaluate: nil
|
|
End:
|