[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
GNU Emacsでは2種類の数値データを扱えます。 整数(integers)と浮動小数点数(floating point numbers)です。 整数は、-3、0、7、13、511のようなちょうどの数です。 これらの値は正確です。 浮動小数点数は、-4.5、0.0、2.71828のように小数部がある数です。 これらは指数表記で表します。 たとえば、1.5e2は150に等しいのです。 この例の`e2'は10の2乗を表し、それを1.5倍します。 浮動小数点数の値は厳密ではありません。 これらの精度には定まった限界があります。
3.1 整数の基本 | Representation and range of integers. | |
3.2 浮動小数点数の基本 | Representation and range of floating point. | |
3.3 数向けの型述語 | Testing for numbers. | |
3.4 数の比較 | Equality and inequality predicates. | |
3.5 数の変換 | Converting float to integer and vice versa. | |
3.6 算術演算 | How to add, subtract, multiply and divide. | |
3.7 丸め演算 | Explicitly rounding floating point numbers. | |
3.8 整数のビット演算 | Logical and, or, not, shifting. | |
3.9 標準数学関数 | Trig, exponential and logarithmic functions. | |
3.10 乱数 | Obtaining random integers, predictable or not. |
整数の値の範囲は計算機に依存します。 最小の範囲は、-134217728から134217727まで(28ビット長、つまり -2**27 から 2**27 - 1)ですが、 これより広い範囲を扱える計算機もあります。 本章の多くの例題では、整数は28長ビットであると仮定します。
Lispリーダは、 先頭に符号があってもよく、最後にピリオドがあってもよい、 数字の列として整数を読み取ります。
1 ; 整数1 1. ; 整数1 +1 ; これも整数1 -1 ; 整数-1 268435457 ; 桁溢れのため、これも整数1 0 ; 整数0 -0 ; 整数0 |
整数を扱うさまざまな関数を理解するには、 特にビット演算(see section 3.8 整数のビット演算)を理解するには、 数を2進表現で考えるとよいです。
28ビット長の2進表現では、10進整数5はつぎのようになります。
0000 0000 0000 0000 0000 0000 0101 |
(4ビットのまとまりごとに空白を1個、 8ビットのまとまりごとに空白を2個挿入して、読みやすくする。)
整数-1はつぎのようになります。
1111 1111 1111 1111 1111 1111 1111 |
-1は、28個の1で表現されます。 (これを2の補数(two's complement)表記と呼ぶ。)
負の数-5は、-1から4を引いて作れます。 10進数4は、2進表記では100です。 したがって、-5は、つぎのようになります。
1111 1111 1111 1111 1111 1111 1011 |
この実装では、28ビット長の2進整数の最大値は、 10進で134,217,727になります。 2進表記では、つぎのようになります。
0111 1111 1111 1111 1111 1111 1111 |
算術関数は、整数がその範囲外に出たかどうか検査しないので、 134,217,727に1を足すと、値は負の数-134,217,728になります。
(+ 1 134217727) => -134217728 => 1000 0000 0000 0000 0000 0000 0000 |
本章で述べる多くの関数は、数の引数としてマーカを受け付けます。 (see section 30. マーカ)。 そのような関数の実際の引数は数かマーカであるので、 それらの引数をしばしばnumber-or-markerという名前で書きます。 引数の値がマーカであるときには、その位置の値を使いバッファは無視します。
浮動小数点数は、整数ではない数を表現するのに便利です。
浮動小数点数の正確な範囲は計算機に依存します。
使用している計算機のC言語のデータ型double
の範囲と同じです。
浮動小数点数の入力構文は、小数点(に続けて1桁以上の小数部)または指数、 あるいは、その両方が必要です。 たとえば、`1500.0'、`15e2'、`15.0e2'、 `1.5e3'、`.15e4'は、同じ1500という値の 浮動小数点数を書き表す5つの方法です。 どれも、まったく等価です。 負の浮動小数点数を書くには、`-1.0'のようにマイナス符号を使います。
現代の計算機はIEEEの浮動小数点数規格に基づいています。
この規格では、浮動小数点数の値には正の無限大と負の無限大があります。
また、NaNすなわち『非数値』(not-a-number)と呼ばれる値の種類もあります。
算術関数は、正しい答えがないときには、このような値を返します。
たとえば、(sqrt -1.0)
はNaNを返します。
実用的には、Emacs Lispでは異なるNaNの値に重要な違いはなく、
特定の場面で正確にはどのNaNの値を使うかの規則もないので、
Emacs Lispではそれらを区別しようとはしません。
浮動小数点数の入力構文はつぎのとおりです。
さらに、IEEEの浮動小数点数では値-0.0
を普通のゼロと区別します
(しかし、equal
と=
は、これらを等しい値と扱う)。
浮動小数点数の2進指数を取り出すには(あるいは、整数の対数を予測するには)、
logb
を使います。
(logb 10) => 3 (logb 10.0e20) => 69 |
本節の関数は、引数が数であるか、とか、特定の種類の数であるか検査します。
関数integerp
とfloatp
は
引数として任意の型のLispオブジェクトを取ります
(さもないと、述語の利用価値がない)。
しかし、述語zerop
の引数には数が必要です。
30.2 マーカ向けの述語の
integer-or-marker-p
とnumber-or-marker-p
も
参照してください。
t
を返し、さもなければnil
を返す。
Emacs 18以前の版にはfloatp
はない。
t
を返し、さもなければnil
を返す。
t
を返し、さもなければnil
を返す。
wholenump
は、
引数が非負整数かどうか調べ、
そうならばt
を返し、さもなければnil
を返す。
0は非負整数として扱う。
t
を返し、さもなければnil
を返す。
引数は数であること。
つぎの2つのフォームは等価。
(zerop x)
== (= x 0)
。
2つの数が数値的に等しいかどうか調べるには、普通、
eq
ではなく=
を使うべきです。
数値的には等しい多くの異なる浮動小数点数が存在しえます。
それらの比較にeq
を使うと、
2つの値が同一オブジェクトかどうか調べることになります。
対照的に、=
はオブジェクトの数値だけを比較します。
現時点では、Emacs Lispにおいて、各整数値は一意なLispオブジェクトです。
したがって、整数に限ればeq
は=
と等価です。
未知の値と整数を比較するためにeq
を使うと便利な場面があります。
というのは、eq
は任意の型の引数を受け付けるので、
eq
は未知の値が数でなくてもエラーを報告しないからです。
対照的に、=
は、引数が数やマーカでないと、エラーを通知します。
しかしながら、Emacsの将来の版で整数の表現方法を変更する場合に備えて、
整数を比較するときであっても、可能ならば、=
を使うほうがよいでしょう。
equal
で数を比較したほうが便利なこともあります。
equal
は、2つの数が同じデータ型
(どちらも整数であるか、どちらも浮動小数点数である)で、
同じ値であれば、2つの数を等しいと扱います。
一方、=
は、整数と浮動小数点数が等しいことを扱えます。
別のことがらもあります。 浮動小数点数演算は厳密ではないので、 2つの浮動小数点数が等しいかどうか調べるのは正しくありません。 普通、近似的に等しいことを調べるほうがよいのです。 つぎの関数はそのようにします。
(defvar fuzz-factor 1.0e-6) (defun approx-equal (x y) (or (and (= x 0) (= y 0)) (< (/ (abs (- x y)) (max (abs x) (abs y))) fuzz-factor))) |
Common Lispに関した注意:Common Lispでは、数の比較にはつねに
=
を使う必要がある。 というのは、Common Lispでは複数ワードの整数を実装しているため、 2つの異なる整数オブジェクトが同じ数値を表すことがありえる。 Emacs Lispでは、整数値の範囲が制限されているため、 任意の値の整数オブジェクトはそれぞれ1つしかない。
t
を返し、さもなければnil
を返す。
t
を返し、等しければnil
を返す。
t
を返し、さもなければnil
を返す。
t
を返し、さもなければnil
を返す。
t
を返し、さもなければnil
を返す。
t
を返し、さもなければnil
を返す。
(max 20) => 20 (max 1 2.5) => 2.5 (max 1 3 2.5) => 3 |
(min -4 1) => -4 |
整数を浮動小数点数に変換するには、
関数float
を使います。
float
はnumberを変更せずに返す。
浮動小数点数を整数に変換する関数は4つあります。 これらの関数は、整数も引数に取りますが、整数引数は変更せずに返します。
divisorを指定すると、切り下げるまえに
numberをdivisorで除算する。
これには、mod
に対応した除算を使い切り下げる。
divisorが0であると、結果はarith-error
になる。
Emacs Lispには、伝統的な四則演算、加算、減算、乗算、除算があります。 除算関数を補う、余りと剰余の関数もあります。 Lispの伝統でもあり、また、多用するので、1を加算したり減算する関数もあります。
これらの関数は、%
を除いて、引数が1つでも浮動小数点数であると、
浮動小数点数を返します。
Emacs Lispでは、算術関数は桁溢れ(オーバフロー)を検査しないことに
注意してください。
つまり、読者の計算機に依存しますが、
(1+ 134217727)
を評価すると-134217728になる場合もあります。
(setq foo 4) => 4 (1+ foo) => 5 |
この関数はC言語の演算子++
の類似ではない。
つまり、変数を増加しない。
したがって、つぎのようになる。
foo => 4 |
変数を増加するには、つぎのようにsetq
を使う必要がある。
(setq foo (1+ foo)) => 5 |
+
は0を返す。
(+) => 0 (+ 1) => 1 (+ 1 2 3 4) => 10 |
-
は、2つの役割、つまり、符号反転と減算を果たす。
-
に1つの引数を指定すると、
その値は、引数の符号を反転したものである。
複数個の引数を指定すると、-
は、
number-or-markerからmore-numbers-or-markersの1つ1つを減算する。
引数を指定しないと結果は0である。
(- 10 1 2 3 4) => 0 (- 10) => -10 (-) => 0 |
*
は1を返す。
(*) => 1 (* 1) => 1 (* 1 2 3 4) => 24 |
すべての引数が整数である場合、結果も整数となる。
つまり、結果は切り捨てになる。
ほとんどの計算機では各除算の結果は0に向けて切り捨てになるが、
負の引数を別の方法で丸める計算機もある。
これは、Lisp関数/
をC言語の除算演算子で実装しているからであり、
C言語の除算演算子では計算機依存に丸めることを許しているからである。
実用上、すべての既知の計算機は標準的な方法で丸める。
整数を0で除算すると、エラーarith-error
を通知する。
(see section 9.5.3 エラー。)
浮動小数点数を0で除算すると、IEEE浮動小数点数を使う計算機では、
無限大かNaNを返す。
さもなければエラーarith-error
を通知する。
(/ 6 2) => 3 (/ 5 2) => 2 (/ 5.0 2) => 2.5 (/ 5 2.0) => 2.5 (/ 5.0 2.0) => 2.5 (/ 25 3 2) => 4 (/ -17 6) => -2 |
原理的には、(/ -17 6)
が-3になる計算機もある。
負の引数では、余りは原理的に計算機依存である。 実用上、すべての既知の計算機は同じようにふるまう。
divisorが0であるとarith-error
になる。
(% 9 4) => 1 (% -9 4) => -1 (% 9 -4) => 1 (% -9 -4) => -1 |
2つの任意の整数dividendとdivisorにおいて、
(+ (% dividend divisor) (* (/ dividend divisor) divisor)) |
は、つねにdividendに等しい。
%
と違い、
mod
は負の引数に対しても厳密に定義された結果を返す。
浮動小数点の引数も許す。
商を(負の無限大に向けて)切り下げて整数にし、
その商を用いて余りを計算する。
divisorが0であるとarith-error
になる。
(mod 9 4) => 1 (mod -9 4) => 3 (mod 9 -4) => -3 (mod -9 -4) => -1 (mod 5.5 2.5) => .5 |
2つの任意の整数dividendとdivisorにおいて、
(+ (mod dividend divisor) (* (floor dividend divisor) divisor)) |
は、つねにdividendに等しい。
ただし、どちらかの引数が浮動小数点数の場合には、
丸め誤差の範囲内で等しい。
floor
については、3.5 数の変換を参照。
関数、ffloor
、fceiling
、fround
、ftruncate
は、
浮動小数点数引数を受け取り、その値に近い整数を値とする浮動小数点数を返します。
ffloor
は、もっとも近いより小さな整数を返します。
fceiling
は、もっとも近いより大きな整数を返します。
ftruncate
は、0に向けて切り捨てたもっとも近い整数を返します。
fround
は、もっとも近い整数を返します。
計算機内部では、整数は2進数、つまり、 ビット(bit、各桁は0か1)列で表現されます。 ビット演算は、そのようなビット列の各ビットごとに作用します。 たとえば、シフト(shifting)は、ビット列を全体として左や右に 1桁以上移動して、その『移動後の』パターンを結果とします。
Emacs Lispにおけるビット演算は整数に限ります。
lsh
は、
integer1のビット列をcount桁左へ、
あるいは、countが負ならば右へずらし、空いたビットには0を詰める。
countが負であれば、lsh
は最左(最上位)ビットに0を詰め、
integer1が負であっても結果は正になる。
これと対照的なのが下のash
。
lsh
の例を2つ示す。
ビットパターンを1桁左へずらす。
ビットパターンの上位ビットはすべて0なので下位8ビットだけを示す。
(lsh 5 1) => 10 ;; 10進数5は、 10進数10になる 00000101 => 00001010 (lsh 7 1) => 14 ;; 10進数7は、10進数14になる 00000111 => 00001110 |
例からわかるように、ビットパターンを1桁左へずらすと、 もとの数値の2倍の数になる。
ビットパターンを2桁左へずらすと、(8ビット長の2進数では)つぎのようになる。
(lsh 3 2) => 12 ;; 10進数3は、10進数12になる 00000011 => 00001100 |
一方、右へずらすとつぎのようになる。
(lsh 6 -1) => 3 ;; 10進数6は、10進数3になる 00000110 => 00000011 (lsh 5 -1) => 2 ;; 10進数5は、10進数2になる 00000101 => 00000010 |
例からわかるように、ビットパターンを1桁右へずらすと、 正の整数の数を2で除して切り下げる。
Emacs Lispのすべての算術関数と同様に、
関数lsh
は桁溢れ(オーバフロー)を検査しないので、
左へずらすと上位ビットを捨てさり数の符号を変えてしまうことがある。
たとえば、28ビット長の計算機では、
134,217,727を左へずらすと-2になる。
(lsh 134217727 1) ; 左シフト => -2 |
28ビット長の実装の2進数では、引数はつぎのようになっている。
;; 10進数134,217,727 0111 1111 1111 1111 1111 1111 1111 |
これを左へずらすと、つぎのようになる
;; 10進数-2 1111 1111 1111 1111 1111 1111 1110 |
ash
(算術シフト(arithmetic shift))は、
integer1のビットをcount桁左へ、あるいは、
countが負ならば右へずらす。
ash
はlsh
と同じ結果になるが、
integer1とcountの両者が負の場合を除く。
この場合、ash
は左の空いたビットには1を入れるが、
lsh
はそのようなビットには0を入れる。
したがって、ash
でビットパターンを1桁右へずらすとつぎのようになる。
(ash -6 -1) => -3 ;; 10進数-6は、10進数-3になる 1111 1111 1111 1111 1111 1111 1010 => 1111 1111 1111 1111 1111 1111 1101 |
対照的に、lsh
でビットパターンを1桁右へずらすとつぎのようになる。
(lsh -6 -1) => 134217725 ;; 10進数-6は、10進数134,217,725になる 1111 1111 1111 1111 1111 1111 1010 => 0111 1111 1111 1111 1111 1111 1101 |
他の例を以下にしめす。
; 28ビット2進値 (lsh 5 2) ; 5 = 0000 0000 0000 0000 0000 0000 0101 => 20 ; = 0000 0000 0000 0000 0000 0001 0100 (ash 5 2) => 20 (lsh -5 2) ; -5 = 1111 1111 1111 1111 1111 1111 1011 => -20 ; = 1111 1111 1111 1111 1111 1110 1100 (ash -5 2) => -20 (lsh 5 -2) ; 5 = 0000 0000 0000 0000 0000 0000 0101 => 1 ; = 0000 0000 0000 0000 0000 0000 0001 (ash 5 -2) => 1 (lsh -5 -2) ; -5 = 1111 1111 1111 1111 1111 1111 1011 => 4194302 ; = 0011 1111 1111 1111 1111 1111 1110 (ash -5 -2) ; -5 = 1111 1111 1111 1111 1111 1111 1011 => -2 ; = 1111 1111 1111 1111 1111 1111 1110 |
たとえば、4ビットの2進数で考えると、 13と12の『論理積』は12になる。 つまり、1101に1100を組み合わせると1100になる。 どちらの2進数も最左の2ビットは1なので、戻り値の最左の2ビットも1になる。 しかし、最右の2ビットは、一方の引数ではそれぞれが0なので、 戻り値の最右の2ビットも0になる。
したがって、つぎのとおり。
(logand 13 12) => 12 |
logand
にまったく引数を指定しないと値-1を返す。
この数は2進表現ではすべて1だけなので、
logand
の恒等元である。
logand
に引数を1つだけ指定するとその引数を返す。
; 28ビット2進値 (logand 14 13) ; 14 = 0000 0000 0000 0000 0000 0000 1110 ; 13 = 0000 0000 0000 0000 0000 0000 1101 => 12 ; 12 = 0000 0000 0000 0000 0000 0000 1100 (logand 14 13 4) ; 14 = 0000 0000 0000 0000 0000 0000 1110 ; 13 = 0000 0000 0000 0000 0000 0000 1101 ; 4 = 0000 0000 0000 0000 0000 0000 0100 => 4 ; 4 = 0000 0000 0000 0000 0000 0000 0100 (logand) => -1 ; -1 = 1111 1111 1111 1111 1111 1111 1111 |
logior
に引数を1つだけ指定するとその引数を返す。
; 28ビット2進値 (logior 12 5) ; 12 = 0000 0000 0000 0000 0000 0000 1100 ; 5 = 0000 0000 0000 0000 0000 0000 0101 => 13 ; 13 = 0000 0000 0000 0000 0000 0000 1101 (logior 12 5 7) ; 12 = 0000 0000 0000 0000 0000 0000 1100 ; 5 = 0000 0000 0000 0000 0000 0000 0101 ; 7 = 0000 0000 0000 0000 0000 0000 0111 => 15 ; 15 = 0000 0000 0000 0000 0000 0000 1111 |
logxor
に引数を1つだけ指定するとその引数を返す。
; 28ビット2進値 (logxor 12 5) ; 12 = 0000 0000 0000 0000 0000 0000 1100 ; 5 = 0000 0000 0000 0000 0000 0000 0101 => 9 ; 9 = 0000 0000 0000 0000 0000 0000 1001 (logxor 12 5 7) ; 12 = 0000 0000 0000 0000 0000 0000 1100 ; 5 = 0000 0000 0000 0000 0000 0000 0101 ; 7 = 0000 0000 0000 0000 0000 0000 0111 => 14 ; 14 = 0000 0000 0000 0000 0000 0000 1110 |
(lognot 5) => -6 ;; 5 = 0000 0000 0000 0000 0000 0000 0101 ;; becomes ;; -6 = 1111 1111 1111 1111 1111 1111 1010 |
これらの数学関数は浮動小数点数に加えて整数も引数として受け付けます。
(asin arg)
の値は-pi/2からpi/2までの数であり、
その正弦(sin)はargに等しい。
しかし、argが([-1, 1]の)範囲を越えていると結果はNaN。
(acos arg)
の値は0からpiまでの数であり、
その余弦(cos)はargに等しい。
しかし、argが([-1, 1]の)範囲を越えていると結果はNaN。
(atan arg)
の値は-pi/2からpi/2までの数であり、
その正接(tan)はargに等しい。
(log10 x)
== (log x 10)
。
決定論的な計算機プログラムは真の乱数を発生できません。 しかし、ほとんどの目的には疑似乱数(pseudo-random numbers)で十分です。 一連の疑似乱数を決定論的な方法で生成します。 それらの数は真の乱数ではありませんが、 乱数列のある種の性質に似た性質があります。 たとえば、疑似乱数列でもすべての可能な数がしばしば等しく生起します。
Emacsでは、疑似乱数は『種』となる数から生成します。
指定した任意の種から始めても、関数random
は同じ数の列を生成します。
Emacsはつねに同じ種の値で計算し始めるため、
それぞれのEmacsの実行でもrandom
は実際には同じ数の列を生成します。
たとえば、あるオペレーティングシステムで、
Emacs開始直後にrandom
を呼ぶとつねに-1457731を返し、
つぎに呼ぶとつねに-7692030を返します。
このような再現性はデバッグには有利です。
予測不可能な乱数が必要ならば(random t)
を実行します。
これは、現在時刻とEmacsプロセスのID番号に基づいて、
新たな種の値を選びます。
limitが正整数ならば、非負でlimit未満になるように値を選ぶ。
limitがt
ならば、
現在時刻とEmacsプロセスのID番号に基づいて、
新たな種の値を選ぶことを意味する。
random
の結果は、Lispにおいて表現可能な任意の整数になる計算機もある。
他の計算機では、結果はある最大値と(負数)最小値のあいだにある。
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |