emacs.d/clones/lispcookbook.github.io/cl-cookbook/numbers.html
2022-08-04 11:37:48 +02:00

705 lines
22 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta name="generator" content=
"HTML Tidy for HTML5 for Linux version 5.2.0">
<title>Numbers</title>
<meta charset="utf-8">
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=
"assets/highlight-lisp.js">
</script>
<script type="text/javascript" src=
"assets/jquery-3.2.1.min.js">
</script>
<script type="text/javascript" src=
"assets/jquery.toc/jquery.toc.min.js">
</script>
<script type="text/javascript" src=
"assets/toggle-toc.js">
</script>
<link rel="stylesheet" href=
"assets/github.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<h1 id="title-xs"><a href="index.html">The Common Lisp Cookbook</a> &ndash; Numbers</h1>
<div id="logo-container">
<a href="index.html">
<img id="logo" src="assets/cl-logo-blue.png"/>
</a>
<div id="searchform-container">
<form onsubmit="duckSearch()" action="javascript:void(0)">
<input id="searchField" type="text" value="" placeholder="Search...">
</form>
</div>
<div id="toc-container" class="toc-close">
<div id="toc-title">Table of Contents</div>
<ul id="toc" class="list-unstyled"></ul>
</div>
</div>
<div id="content-container">
<h1 id="title-non-xs"><a href="index.html">The Common Lisp Cookbook</a> &ndash; Numbers</h1>
<!-- Announcement we can keep for 1 month or more. I remove it and re-add it from time to time. -->
<p class="announce">
📹 <a href="https://www.udemy.com/course/common-lisp-programming/?couponCode=6926D599AA-LISP4ALL">NEW! Learn Lisp in videos and support our contributors with this 40% discount.</a>
</p>
<p class="announce-neutral">
📕 <a href="index.html#download-in-epub">Get the EPUB and PDF</a>
</p>
<div id="content"
<p>Common Lisp has a rich set of numerical types, including integer,
rational, floating point, and complex.</p>
<p>Some sources:</p>
<ul>
<li><a href="https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node16.html#SECTION00610000000000000000"><code>Numbers</code></a> in Common Lisp the Language, 2nd Edition</li>
<li><a href="http://www.gigamonkeys.com/book/numbers-characters-and-strings.html"><code>Numbers, Characters and Strings</code></a>
in Practical Common Lisp</li>
</ul>
<h2 id="introduction">Introduction</h2>
<h3 id="integer-types">Integer types</h3>
<p>Common Lisp provides a true integer type, called <code>bignum</code>, limited only by the total
memory available (not the machine word size). For example this would
overflow a 64 bit integer by some way:</p>
<pre><code class="language-lisp">* (expt 2 200)
1606938044258990275541962092341162602522202993782792835301376
</code></pre>
<p>For efficiency, integers can be limited to a fixed number of bits,
called a <code>fixnum</code> type. The range of integers which can be represented
is given by:</p>
<pre><code class="language-lisp">* most-positive-fixnum
4611686018427387903
* most-negative-fixnum
-4611686018427387904
</code></pre>
<p>Functions which operate on or evaluate to integers include:</p>
<ul>
<li><a href="http://clhs.lisp.se/Body/f_sqrt_.htm"><code>isqrt</code></a>, which returns the greatest integer less than or equal to the
exact positive square root of natural.</li>
</ul>
<pre><code class="language-lisp">* (isqrt 10)
3
* (isqrt 4)
2
</code></pre>
<ul>
<li><a href="http://clhs.lisp.se/Body/f_gcd.htm"><code>gcd</code></a> to find the Greatest Common Denominator</li>
<li><a href="http://clhs.lisp.se/Body/f_lcm.htm#lcm"><code>lcm</code></a> for the Least Common Multiple.</li>
</ul>
<p>Like other low-level programming languages, Common Lisp provides literal
representation for hexadecimals and other radixes up to 36. For example:</p>
<pre><code class="language-lisp">* #xFF
255
* #2r1010
10
* #4r33
15
* #8r11
9
* #16rFF
255
* #36rz
35
</code></pre>
<h3 id="rational-types">Rational types</h3>
<p>Rational numbers of type <a href="http://clhs.lisp.se/Body/t_ratio.htm"><code>ratio</code></a> consist of two <code>bignum</code>s, the
numerator and denominator. Both can therefore be arbitrarily large:</p>
<pre><code class="language-lisp">* (/ (1+ (expt 2 100)) (expt 2 100))
1267650600228229401496703205377/1267650600228229401496703205376
</code></pre>
<p>It is a subtype of the <a href="http://clhs.lisp.se/Body/t_ration.htm#rational"><code>rational</code></a> class, along with
<a href="http://clhs.lisp.se/Body/t_intege.htm#integer"><code>integer</code></a>.</p>
<h3 id="floating-point-types">Floating point types</h3>
<p>See <a href="https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node19.html">Common Lisp the Language, 2nd Edition, section 2.1.3</a>.</p>
<p>Floating point types attempt to represent the continuous real numbers
using a finite number of bits. This means that many real numbers
cannot be represented, but are approximated. This can lead to some nasty
surprises, particularly when converting between base-10 and the base-2
internal representation. If you are working with floating point
numbers then reading <a href="https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html">What Every Computer Scientist Should Know About
Floating-Point Arithmetic</a> is highly
recommended.</p>
<p>The Common Lisp standard allows for several floating point types. In
order of increasing precision these are: <code>short-float</code>,
<code>single-float</code>, <code>double-float</code>, and <code>long-float</code>. Their precisions are
implementation dependent, and it is possible for an implementation to
have only one floating point precision for all types.</p>
<p>The constants <a href="http://clhs.lisp.se/Body/v_short_.htm"><code>short-float-epsilon</code>, <code>single-float-epsilon</code>,
<code>double-float-epsilon</code> and <code>long-float-epsilon</code></a> give
a measure of the precision of the floating point types, and are
implementation dependent.</p>
<h4 id="floating-point-literals">Floating point literals</h4>
<p>When reading floating point numbers, the default type is set by the special
variable <a href="http://clhs.lisp.se/Body/v_rd_def.htm"><code>*read-default-float-format*</code></a>. By default
this is <code>SINGLE-FLOAT</code>, so if you want to ensure that a number is read as double
precision then put a <code>d0</code> suffix at the end</p>
<pre><code class="language-lisp">* (type-of 1.24)
SINGLE-FLOAT
* (type-of 1.24d0)
DOUBLE-FLOAT
</code></pre>
<p>Other suffixes are <code>s</code> (short), <code>f</code> (single float), <code>d</code> (double
float), <code>l</code> (long float) and <code>e</code> (default; usually single float).</p>
<p>The default type can be changed, but note that this may break packages
which assume <code>single-float</code> type.</p>
<pre><code class="language-lisp">* (setq *read-default-float-format* 'double-float)
* (type-of 1.24)
DOUBLE-FLOAT
</code></pre>
<p>Note that unlike in some languages, appending a single decimal point
to the end of a number does not make it a float:</p>
<pre><code class="language-lisp">* (type-of 10.)
(INTEGER 0 4611686018427387903)
* (type-of 10.0)
SINGLE-FLOAT
</code></pre>
<h4 id="floating-point-errors">Floating point errors</h4>
<p>If the result of a floating point calculation is too large then a floating
point overflow occurs. By default in <a href="http://www.sbcl.org/">SBCL</a> (and other implementations)
this results in an error condition:</p>
<pre><code class="language-lisp">* (exp 1000)
; Evaluation aborted on #&lt;FLOATING-POINT-OVERFLOW {10041720B3}&gt;.
</code></pre>
<p>The error can be caught and handled, or this behaviour can be
changed, to return <code>+infinity</code>. In SBCL this is:</p>
<pre><code class="language-lisp">* (sb-int:set-floating-point-modes :traps '(:INVALID :DIVIDE-BY-ZERO))
* (exp 1000)
#.SB-EXT:SINGLE-FLOAT-POSITIVE-INFINITY
* (/ 1 (exp 1000))
0.0
</code></pre>
<p>The calculation now silently continues, without an error condition.</p>
<p>A similar functionality to disable floating overflow errors
exists in <a href="https://ccl.clozure.com/">CCL</a>:</p>
<pre><code class="language-lisp">* (set-fpu-mode :overflow nil)
</code></pre>
<p>In SBCL the floating point modes can be inspected:</p>
<pre><code class="language-lisp">* (sb-int:get-floating-point-modes)
(:TRAPS (:OVERFLOW :INVALID :DIVIDE-BY-ZERO) :ROUNDING-MODE :NEAREST
:CURRENT-EXCEPTIONS NIL :ACCRUED-EXCEPTIONS NIL :FAST-MODE NIL)
</code></pre>
<h4 id="arbitrary-precision">Arbitrary precision</h4>
<p>For arbitrary high precision calculations there is the
<a href="http://quickdocs.org/computable-reals/">computable-reals</a> library on QuickLisp:</p>
<pre><code class="language-lisp">* (ql:quickload :computable-reals)
* (use-package :computable-reals)
* (sqrt-r 2)
+1.41421356237309504880...
* (sin-r (/r +pi-r+ 2))
+1.00000000000000000000...
</code></pre>
<p>The precision to print is set by <code>*PRINT-PREC*</code>, by default 20</p>
<pre><code class="language-lisp">* (setq *PRINT-PREC* 50)
* (sqrt-r 2)
+1.41421356237309504880168872420969807856967187537695...
</code></pre>
<h3 id="complex-types">Complex types</h3>
<p>There are 5 types of complex number: The real and imaginary parts must
be of the same type, and can be rational, or one of the floating point
types (short, single, double or long).</p>
<p>Complex values can be created using the <code>#C</code> reader macro or the function
<a href="http://clhs.lisp.se/Body/f_comp_2.htm#complex"><code>complex</code></a>. The reader macro does not allow the use of expressions
as real and imaginary parts:</p>
<pre><code class="language-lisp">* #C(1 1)
#C(1 1)
* #C((+ 1 2) 5)
; Evaluation aborted on #&lt;TYPE-ERROR expected-type: REAL datum: (+ 1 2)&gt;.
* (complex (+ 1 2) 5)
#C(3 5)
</code></pre>
<p>If constructed with mixed types then the higher precision type will be used for both parts.</p>
<pre><code class="language-lisp">* (type-of #C(1 1))
(COMPLEX (INTEGER 1 1))
* (type-of #C(1.0 1))
(COMPLEX (SINGLE-FLOAT 1.0 1.0))
* (type-of #C(1.0 1d0))
(COMPLEX (DOUBLE-FLOAT 1.0d0 1.0d0))
</code></pre>
<p>The real and imaginary parts of a complex number can be extracted using
<a href="http://clhs.lisp.se/Body/f_realpa.htm"><code>realpart</code> and <code>imagpart</code></a>:</p>
<pre><code class="language-lisp">* (realpart #C(7 9))
7
* (imagpart #C(4.2 9.5))
9.5
</code></pre>
<h4 id="complex-arithmetic">Complex arithmetic</h4>
<p>Common Lisps mathematical functions generally handle complex numbers,
and return complex numbers when this is the true result. For example:</p>
<pre><code class="language-lisp">* (sqrt -1)
#C(0.0 1.0)
* (exp #C(0.0 0.5))
#C(0.87758255 0.47942555)
* (sin #C(1.0 1.0))
#C(1.2984576 0.63496387)
</code></pre>
<h2 id="reading-numbers-from-strings">Reading numbers from strings</h2>
<p>The <a href="http://clhs.lisp.se/Body/f_parse_.htm"><code>parse-integer</code></a> function reads an integer from a string.</p>
<p>The <a href="https://github.com/soemraws/parse-float/blob/master/parse-float.lisp">parse-float</a> library provides a parser which cannot evaluate
arbitrary expressions, so should be safer to use on untrusted input:</p>
<pre><code class="language-lisp">* (ql:quickload :parse-float)
* (use-package :parse-float)
* (parse-float "23.4e2" :type 'double-float)
2340.0d0
6
</code></pre>
<p>See the <a href="strings.html#converting-a-string-to-a-number">strings section</a> on converting between strings and numbers.</p>
<h2 id="converting-numbers">Converting numbers</h2>
<p>Most numerical functions automatically convert types as needed.
The <code>coerce</code> function converts objects from one type to another,
including numeric types.</p>
<p>See <a href="https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node130.html">Common Lisp the Language, 2nd Edition, section 12.6</a>.</p>
<h3 id="convert-float-to-rational">Convert float to rational</h3>
<p>The <a href="http://clhs.lisp.se/Body/f_ration.htm"><code>rational</code> and <code>rationalize</code> functions</a> convert
a real numeric argument into a rational. <code>rational</code> assumes that floating
point arguments are exact; <code>rationalize</code> exploits the fact that floating point
numbers are only exact to their precision, so can often find a simpler
rational number.</p>
<h3 id="convert-rational-to-integer">Convert rational to integer</h3>
<p>If the result of a calculation is a rational number where the numerator
is a multiple of the denominator, then it is automatically converted
to an integer:</p>
<pre><code class="language-lisp">* (type-of (* 1/2 4))
(INTEGER 0 4611686018427387903)
</code></pre>
<h2 id="rounding-floating-point-and-rational-numbers">Rounding floating-point and rational numbers</h2>
<p>The <a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_floorc.htm"><code>ceiling</code>, <code>floor</code>, <code>round</code> and <code>truncate</code></a> functions
convert floating point or rational numbers to integers. The difference
between the result and the input is returned as the second value, so that the
input is the sum of the two outputs.</p>
<pre><code class="language-lisp">* (ceiling 1.42)
2
-0.58000004
* (floor 1.42)
1
0.41999996
* (round 1.42)
1
0.41999996
* (truncate 1.42)
1
0.41999996
</code></pre>
<p>There is a difference between <code>floor</code> and <code>truncate</code> for negative
numbers:</p>
<pre><code class="language-lisp">* (truncate -1.42)
-1
-0.41999996
* (floor -1.42)
-2
0.58000004
* (ceiling -1.42)
-1
-0.41999996
</code></pre>
<p>Similar functions <code>fceiling</code>, <code>ffloor</code>, <code>fround</code> and <code>ftruncate</code>
return the result as floating point, of the same type as their
argument:</p>
<pre><code class="language-lisp">* (ftruncate 1.3)
1.0
0.29999995
* (type-of (ftruncate 1.3))
SINGLE-FLOAT
* (type-of (ftruncate 1.3d0))
DOUBLE-FLOAT
</code></pre>
<h2 id="comparing-numbers">Comparing numbers</h2>
<p>See <a href="https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node124.html">Common Lisp the Language, 2nd Edition, Section 12.3</a>.</p>
<p>The <code>=</code> predicate returns <code>T</code> if all arguments are numerically equal.
Note that comparison of floating point numbers includes some margin
for error, due to the fact that they cannot represent all real
numbers and accumulate errors.</p>
<p>The constant <a href="http://clhs.lisp.se/Body/v_short_.htm"><code>single-float-epsilon</code></a> is the smallest
number which will cause an <code>=</code> comparison to fail, if it is added to 1.0:</p>
<pre><code class="language-lisp">* (= (+ 1s0 5e-8) 1s0)
T
* (= (+ 1s0 6e-8) 1s0)
NIL
</code></pre>
<p>Note that this does not mean that a <code>single-float</code> is always precise
to within <code>6e-8</code>:</p>
<pre><code class="language-lisp">* (= (+ 10s0 4e-7) 10s0)
T
* (= (+ 10s0 5e-7) 10s0)
NIL
</code></pre>
<p>Instead this means that <code>single-float</code> is precise to approximately
seven digits. If a sequence of calculations are performed, then error
can accumulate and a larger error margin may be needed. In this case
the absolute difference can be compared:</p>
<pre><code class="language-lisp">* (&lt; (abs (- (+ 10s0 5e-7)
10s0))
1s-6)
T
</code></pre>
<p>When comparing numbers with <code>=</code> mixed types are allowed. To test both
numerical value and type use <code>eql</code>:</p>
<pre><code class="language-lisp">* (= 3 3.0)
T
* (eql 3 3.0)
NIL
</code></pre>
<h2 id="operating-on-a-series-of-numbers">Operating on a series of numbers</h2>
<p>Many Common Lisp functions operate on sequences, which can be either lists
or vectors (1D arrays). See the section on
<a href="data-structures.html#mapping-map-mapcar-remove-if-not">mapping</a>.</p>
<p>Operations on multidimensional arrays are discussed in
<a href="arrays.html">this section</a>.</p>
<p>Libraries are available for defining and operating on lazy sequences,
including “infinite” sequences of numbers. For example</p>
<ul>
<li><a href="https://common-lisp.net/project/clazy/">Clazy</a> which is on QuickLisp.</li>
<li><a href="https://github.com/mikelevins/folio2">folio2</a> on QuickLisp. Includes an interface to the</li>
<li><a href="https://github.com/tokenrove/series/wiki/Documentation">Series</a> package for efficient sequences.</li>
<li><a href="https://github.com/fredokun/lisp-lazy-seq">lazy-seq</a>.</li>
</ul>
<h2 id="working-with-roman-numerals">Working with Roman numerals</h2>
<p>The <code>format</code> function can convert numbers to roman numerals with the
<code>~@r</code> directive:</p>
<pre><code class="language-lisp">* (format nil "~@r" 42)
"XLII"
</code></pre>
<p>There is a <a href="https://gist.github.com/tormaroe/90ddd9dc7cc191040be4">gist by tormaroe</a> for reading roman numerals.</p>
<h2 id="generating-random-numbers">Generating random numbers</h2>
<p>The <a href="http://clhs.lisp.se/Body/f_random.htm#random"><code>random</code></a> function generates either integer or floating point
random numbers, depending on the type of its argument.</p>
<pre><code class="language-lisp">* (random 10)
7
* (type-of (random 10))
(INTEGER 0 4611686018427387903)
* (type-of (random 10.0))
SINGLE-FLOAT
* (type-of (random 10d0))
DOUBLE-FLOAT
</code></pre>
<p>In SBCL a <a href="https://en.wikipedia.org/wiki/Mersenne_Twister">Mersenne Twister</a> pseudo-random number generator
is used. See section <a href="http://www.sbcl.org/manual/#Random-Number-Generation">7.13 of the SBCL manual</a> for details.</p>
<p>The random seed is stored in <a href="http://quickdocs.org/random-state/"><code>*random-state*</code></a> whose internal
representation is implementation dependent. The function
<a href="http://clhs.lisp.se/Body/f_mk_rnd.htm"><code>make-random-state</code></a> can be used to make new random
states, or copy existing states.</p>
<p>To use the same set of random numbers multiple times,
<code>(make-random-state nil)</code> makes a copy of the current <code>*random-state*</code>:</p>
<pre><code class="language-lisp">* (dotimes (i 3)
(let ((*random-state* (make-random-state nil)))
(format t "~a~%"
(loop for i from 0 below 10 collecting (random 10)))))
(8 3 9 2 1 8 0 0 4 1)
(8 3 9 2 1 8 0 0 4 1)
(8 3 9 2 1 8 0 0 4 1)
</code></pre>
<p>This generates 10 random numbers in a loop, but each time the sequence
is the same because the <code>*random-state*</code> special variable is dynamically
bound to a copy of its state before the <code>let</code> form.</p>
<p>Other resources:</p>
<ul>
<li>The <a href="http://quickdocs.org/random-state/">random-state</a> package is available on QuickLisp, and
provides a number of portable random number generators.</li>
</ul>
<h2 id="bit-wise-operation">Bit-wise Operation</h2>
<p>Common Lisp also provides many functions to perform bit-wise arithmetic
operations. Some commonly used ones are listed below, together with their
C/C++ equivalence.</p>
<table class="table table-bordered table-stripped">
<thead>
<tr>
<th>Common Lisp</th>
<th>C/C++</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>(logand a b c)</code></td>
<td><code>a &amp; b &amp; c</code></td>
<td>Bit-wise AND of multiple operands</td>
</tr>
<tr>
<td><code>(logior a b c)</code></td>
<td><code>a | b | c</code></td>
<td>Bit-wise OR of multiple arguments</td>
</tr>
<tr>
<td><code>(lognot a)</code></td>
<td><code>~a</code></td>
<td>Bit-wise NOT of single operand</td>
</tr>
<tr>
<td><code>(logxor a b c)</code></td>
<td><code>a ^ b ^ c</code></td>
<td>Bit-wise exclusive or (XOR) or multiple operands</td>
</tr>
<tr>
<td><code>(ash a 3)</code></td>
<td><code>a &lt;&lt; 3</code></td>
<td>Bit-wise left shift</td>
</tr>
<tr>
<td><code>(ash a -3)</code></td>
<td><code>a &gt;&gt; 3</code></td>
<td>Bit-wise right shift</td>
</tr>
</tbody>
</table>
<p>Negative numbers are treated as twos-complements. If you have forgotten this,
please refer to the <a href="https://en.wikipedia.org/wiki/Twos_complement">Wiki page</a>.</p>
<p>For example:</p>
<pre><code class="language-lisp">* (logior 1 2 4 8)
15
;; Explanation:
;; 0001
;; 0010
;; 0100
;; | 1000
;; -------
;; 1111
* (logand 2 -3 4)
0
;; Explanation:
;; 0010 (2)
;; 1101 (two's complement of -3)
;; &amp; 0100 (4)
;; -------
;; 0000
* (logxor 1 3 7 15)
10
;; Explanation:
;; 0001
;; 0011
;; 0111
;; ^ 1111
;; -------
;; 1010
* (lognot -1)
0
;; Explanation:
;; 11 -&gt; 00
* (lognot -3)
2
;; 101 -&gt; 010
* (ash 3 2)
12
;; Explanation:
;; 11 -&gt; 1100
* (ash -5 -2)
-2
;; Explanation
;; 11011 -&gt; 110
</code></pre>
<p>Please see the <a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_logand.htm">CLHS page</a> for a more detailed explanation
or other bit-wise functions.</p>
<p class="page-source">
Page source: <a href="https://github.com/LispCookbook/cl-cookbook/blob/master/numbers.md">numbers.md</a>
</p>
</div>
<script type="text/javascript">
// Don't write the TOC on the index.
if (window.location.pathname != "/cl-cookbook/") {
$("#toc").toc({
content: "#content", // will ignore the first h1 with the site+page title.
headings: "h1,h2,h3,h4"});
}
$("#two-cols + ul").css({
"column-count": "2",
});
$("#contributors + ul").css({
"column-count": "4",
});
</script>
<div>
<footer class="footer">
<hr/>
&copy; 2002&ndash;2021 the Common Lisp Cookbook Project
</footer>
</div>
<div id="toc-btn">T<br>O<br>C</div>
</div>
<script text="javascript">
HighlightLisp.highlight_auto({className: null});
</script>
<script type="text/javascript">
function duckSearch() {
var searchField = document.getElementById("searchField");
if (searchField && searchField.value) {
var query = escape("site:lispcookbook.github.io/cl-cookbook/ " + searchField.value);
window.location.href = "https://duckduckgo.com/?kj=b2&kf=-1&ko=1&q=" + query;
// https://duckduckgo.com/params
// kj=b2: blue header in results page
// kf=-1: no favicons
}
}
</script>
<script async defer data-domain="lispcookbook.github.io/cl-cookbook" src="https://plausible.io/js/plausible.js"></script>
</body>
</html>