730 lines
23 KiB
HTML
730 lines
23 KiB
HTML
<!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> – 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> – 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 style="font-size: 120%" href="https://www.udemy.com/course/common-lisp-programming/?couponCode=LISPMACROSPOWER" title="This course is under a paywall on the Udemy platform. Several videos are freely available so you can judge before diving in. vindarel is (I am) the main contributor to this Cookbook."> Discover vindarel's Lisp course in videos with this September coupon.</a>
|
||
<strong>
|
||
Recently added: 18 videos on MACROS.
|
||
</strong>
|
||
<a style="font-size: 90%" href="https://github.com/vindarel/common-lisp-course-in-videos/">Learn more</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 #<FLOATING-POINT-OVERFLOW {10041720B3}>.
|
||
</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 #<TYPE-ERROR expected-type: REAL datum: (+ 1 2)>.
|
||
|
||
* (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 Lisp’s 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">* (< (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>
|
||
|
||
<style>
|
||
table, th, td {
|
||
border: 1px solid black;
|
||
border-collapse: collapse;
|
||
}
|
||
th, td {
|
||
padding: 5px;
|
||
}
|
||
th {
|
||
text-align: left;
|
||
}
|
||
</style>
|
||
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Common Lisp</th>
|
||
<th>C/C++</th>
|
||
<th>Description</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>(logand a b c)</td>
|
||
<td>a & b & c</td>
|
||
<td>Bit-wise AND of multiple operands</td>
|
||
</tr>
|
||
<tr>
|
||
<td>(logior a b c)</td>
|
||
<td>a | b | c</td>
|
||
<td>Bit-wise OR of multiple operands</td>
|
||
</tr>
|
||
<tr>
|
||
<td>(lognot a)</td>
|
||
<td>~a</td>
|
||
<td>Bit-wise NOT of single operands</td>
|
||
</tr>
|
||
<tr>
|
||
<td>(logxor a b c)</td>
|
||
<td>a ^ b ^ c</td>
|
||
<td>Bit-wise exclusive or (XOR) of multiple operands</td>
|
||
</tr>
|
||
<tr>
|
||
<td>(ash a 3)</td>
|
||
<td>a << 3</td>
|
||
<td>Bit-wise left shift</td>
|
||
</tr>
|
||
<tr>
|
||
<td>(ash a -3)</td>
|
||
<td>a >> 3</td>
|
||
<td>Bit-wise right shift</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<!-- epub-exclude-start -->
|
||
<p><br />
|
||
<!-- epub-exclude-end --></p>
|
||
|
||
<p>Negative numbers are treated as two’s-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)
|
||
;; & 0100 (4)
|
||
;; -------
|
||
;; 0000
|
||
|
||
* (logxor 1 3 7 15)
|
||
10
|
||
|
||
;; Explanation:
|
||
;; 0001
|
||
;; 0011
|
||
;; 0111
|
||
;; ^ 1111
|
||
;; -------
|
||
;; 1010
|
||
|
||
* (lognot -1)
|
||
0
|
||
;; Explanation:
|
||
;; 11 -> 00
|
||
|
||
* (lognot -3)
|
||
2
|
||
;; 101 -> 010
|
||
|
||
* (ash 3 2)
|
||
12
|
||
;; Explanation:
|
||
;; 11 -> 1100
|
||
|
||
* (ash -5 -2)
|
||
-2
|
||
;; Explanation
|
||
;; 11011 -> 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/>
|
||
© 2002–2023 the Common Lisp Cookbook Project
|
||
<div>
|
||
📹 Discover <a style="color: darkgrey; text-decoration: underline", href="https://www.udemy.com/course/common-lisp-programming/?referralCode=2F3D698BBC4326F94358">vindarel's Lisp course on Udemy</a>
|
||
</div>
|
||
</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>
|