For Gauche 0.9.5


Next: , Previous: , Up: 組み込みライブラリ   [Contents][Index]

6.3 数値

Gaucheは次のタイプの数値をサポートしています。

多倍長の正確な整数

メモリの許す限りの精度が扱えます。

多倍長の正確な非整数の有理数

分母と分子は正確な整数で表現されます。 メモリの許す限りの精度が扱えます。

浮動小数点の不正確な実数

実装に使われるC言語のdouble型で表現されます。通常IEEE 64bit浮動小数点数です。

浮動小数点の不正確な複素数

実部と虚部はそれぞれ浮動小数点の不正確な実数で表現されます。


Next: , Previous: , Up: 数値   [Contents][Index]

6.3.1 数値クラス

Builtin Class: <number>
Builtin Class: <complex>
Builtin Class: <real>
Builtin Class: <rational>
Builtin Class: <integer>

数値オブジェクトのクラス階層を構成します。<complex><number>を継承し、<real><complex>を継承し、 <rational><real>を継承し、 <integer><rational>を継承します。

これらのクラスはR7RSで定義されている数値の階層とは必ずしも対応しません。 特に、<integer>クラスのインスタンスはR7RSでいうexact integerのみになります。

(integer? 1)        ⇒ #t
(is-a? 1 <integer>) ⇒ #t
(is-a? 1 <real>)    ⇒ #t

(integer? 1.0)        ⇒ #t
(is-a? 1.0 <integer>) ⇒ #f
(is-a? 1.0 <real>)    ⇒ #t

(class-of (expt 2 100)) ⇒ #<class <integer>>
(class-of (sqrt -3)) ⇒ #<class <complex>>

Next: , Previous: , Up: 数値   [Contents][Index]

6.3.2 数値に関する述語

Function: number? obj
Function: complex? obj
Function: real? obj
Function: rational? obj
Function: integer? obj

[R7RS] objがそれぞれ数、複素数、実数、有理数、整数ならば#tを返します。 Gaucheでは、数の集合は複素数の集合と同一であり、有理数の集合は +inf.0, -inf.0, +nan.0を除いた実数の集合と同一 (浮動小数点数が有限精度であるため)です。

(complex? 3+4i)   ⇒ #t
(complex? 3)      ⇒ #t
(real? 3)         ⇒ #t
(real? -2.5+0.0i) ⇒ #t
(real? #e1e10)    ⇒ #t
(integer? 3+0i)   ⇒ #t
(integer? 3.0)    ⇒ #t

(real? +inf.0)     ⇒ #t
(real? +nan.0)     ⇒ #t
(rational? +inf.0) ⇒ #f
(rational? +nan.0) ⇒ #f

R6RSでは正確性についてより厳密な定義がなされ、特に 非正確なゼロを虚数部に持つ複素数は実数ではないと規定されています。 Gaucheは今のところ正確な複素数を持たず、虚部がゼロの複素数は 自動的に実数に変換されます。従ってR6RSのコードのうち、 (real? 1+0.0i)#fであることを当てにしているものは うまく動かないでしょう。

Function: real-valued? obj
Function: rational-valued? obj
Function: integer-valued? obj

[R6RS] Gaucheではこれらの手続きはそれぞれreal?rational?、 およびinteger?の別名となっています。これらはR6RSコードとの互換性のために 提供されています。

R6RSで規定されている、これらの手続きと-valuedがついていない手続きの違いは、 これらの手続きは非正確なゼロの虚部を持つ複素数に対しても#tを返すという ことです。Gaucheではゼロの虚部を持つ複素数は実数とみなしているので、 この違いは現れません。

Function: exact? obj
Function: inexact? obj

[R7RS] objがそれぞれ正確な数、不正確な数ならば#tを返します。

(exact? 1)       ⇒ #t
(exact? 1.0)     ⇒ #f
(inexact? 1)     ⇒ #f
(inexact? 1.0)   ⇒ #t

(exact? (modulo 5 3)) ⇒ #t
(inexact? (modulo 5 3.0)) ⇒ #f
Function: exact-integer? obj

[R7RS] (and (exact? obj) (integer? obj))と等価ですが、より高速です。

Function: zero? z

[R7RS] 数値zがゼロに等しければ#tを返します。

(zero? 1)        ⇒ #f
(zero? 0)        ⇒ #t
(zero? 0.0)      ⇒ #t
(zero? 0.0+0.0i) ⇒ #t
Function: positive? x
Function: negative? x

[R7RS] 実数xがそれぞれ正または負なら#tを返します。 非実数を渡すとエラーになります。

Function: finite? z
Function: infinite? z
Function: nan? z

[R7RS] 実数に対して、それが有限、無限、NaNであればそれぞれ#tを返します。

非実数の複素数に対しては、finite?は実数部と仮数部がともに 有限なら#tを、infinite?は実数部と仮数部の少なくともどちらかが 無限なら#tを、nan?は実数部と仮数部の少なくともどちらかが NaNなら#tを返します。(これはR6RSとは非互換です。R6RSでは これらの手続きは引数に非実数の数が与えられた場合はエラーを通知しなければならないからです。)

R7RSではこれらの手続きは(scheme inexact)ライブラリにあります。

Function: odd? n
Function: even? n

[R7RS] 整数nがそれぞれ奇数または偶数なら#tを返します。 非整数を渡すとエラーになります。

(odd? 3)     ⇒ #t
(even? 3)    ⇒ #f
(odd? 3.0)   ⇒ #t
Function: fixnum? n
Function: bignum? n

nが正確な整数で、かつ内部的にそれぞれfixnumもしくはbignum で表現されているときに#tを返します。 通常のSchemeプログラムは整数の内部表現を気にする必要はありません。 これらの手続きは、ある種の最適化を行う低レベル手続きのために用意されています。


Next: , Previous: , Up: 数値   [Contents][Index]

6.3.3 数値の比較

Function: = z1 z2 z3 …

[R7RS] 与えられた全ての数値zが等しければ#tを返します。

(= 2 2)          ⇒ #t
(= 2 3)          ⇒ #f
(= 2 2.0)        ⇒ #t
(= 2 2.0 2.0+0i) ⇒ #t
(= 2/4 1/2)      ⇒ #t
Function: < x1 x2 x3 …
Function: <= x1 x2 x3 …
Function: > x1 x2 x3 …
Function: >= x1 x2 x3 …

[R7RS] 与えられた全ての実数xがそれぞれ単調増加、単調非減少、単調減少、単調非増加している 場合に#tを返します。

Function: max x1 x2 …
Function: min x1 x2 …

[R7RS] 与えられた実数のうち、それぞれ最大と最小のものを返します。 引数にNaNが含まれていた場合は、NaNが返されます。

コレクションからの選択と探索find-minfind-maxも参照。

Function: min&max x1 x2 …

与えられた実数から、最大値と最小値の二つの値を返します。

コレクションからの選択と探索find-min&maxも参照。


Next: , Previous: , Up: 数値   [Contents][Index]

6.3.4 数値の演算

Function: + z …
Function: * z …

[R7RS] 与えられた数の和と積をそれぞれ返します。引数が与えられない場合、 (+) は 0、 (*) は 1 となります。

Function: - z1 z2 …
Function: / z1 z2 …

[R7RS] 一つだけ数値が与えられた場合、それぞれnegationと逆数を返します。

2つ以上の数値が与えられた場合、それぞれ次の結果を返します。

z1 - z2 - z3z1 / z2 / z3
(- 3)       ⇒ -3
(- -3.0)    ⇒ 3.0
(- 5+2i)    ⇒ -5.0-2.0i
(/ 3)       ⇒ 1/3
(/ 5+2i)    ⇒ 0.172413793103448-0.0689655172413793i

(- 5 2 1)     ⇒ 2
(- 5 2.0 1)   ⇒ 2.0
(- 5+3i -i)   ⇒ 5.0+2.0i
(/ 14 6)      ⇒ 7/3
(/ 6+2i 2)    ⇒ 3.0+1.0i

註:0.8.8までGaucheは正確な有理数をサポートしておらず、 それ以前は除数と被除数がともに正確な数であっても商が整数にならなければ 結果は非正確な数へと変換されていました。今のGaucheはそうではありません。

既存のコードが以前のGaucheのふるまいを当てにしていた場合、 速度が大きく低下する可能性があります。正確な有理数の演算は 浮動小数点数の演算よりはるかに遅いからです。 (正確な結果を得たいのでない場合は)下に述べる/.を使うと良いでしょう。

Function: +. z …
Function: *. z …
Function: -. z1 z2 …
Function: /. z1 z2 …

+*-/と同様ですが、引数は不正確な 数へと変換され、結果も常に不正確な数となります。 正確数による計算が不要で、bignumや正確な有理数をうっかり使ってしまう ことによるオーバヘッドを避けたい時に便利です。

Function: abs z

[R7RS+] 実数のzに対しては、その絶対値を返します。 複素数のzに対しては、そのmagnitudeを返します。 複素数を扱うのはGaucheの拡張です。

(abs -1)   ⇒ 1
(abs -1.0) ⇒ 1.0
(abs 1+i)  ⇒ 1.4142135623731
Function: quotient n1 n2
Function: remainder n1 n2
Function: modulo n1 n2

[R7RS] 整数n1を整数n2で割った商(quotient)および余り(remainder, modulo) を返します。 n1n2の両方が正確な数値の時のみ、戻り値は正確な数値になります。

remaindermodulo はどちらかの引数が負の時に異なる値を返します。 Remainder R と商 Q とは次の関係があります。

  n1 = Q * n2 + R

ここで商について abs(Q) = floor(abs(n1)/abs(n2)) ですから、Rの符号は常にn1と同じになります。

一方、moduloはn2が正の時はn1の符号に関わらず期待したように動作します (例: (modulo -1 n2) == n2 - 1)。 n2が負の場合は次の式によって正の場合にマップできます。

  modulo(n1, n2) = -modulo(-n1, -n2)

したがって、moduloの結果の符号は常にn2の符号と同じになります。

(remainder 10 3)    ⇒ 1
(modulo 10 3)       ⇒ 1

(remainder -10 3)   ⇒ -1
(modulo -10 3)      ⇒ 2

(remainder 10 -3)   ⇒ 1
(modulo 10 -3)      ⇒ -2

(remainder -10 -3)  ⇒ -1
(modulo -10 -3)     ⇒ -1
Function: quotient&remainder n1 n2

整数n1を整数n2で割った商(quotient)および余り(remainder) を同時に計算し、2つの値として返します。

Function: div x y
Function: mod x y
Function: div-and-mod x y
Function: div0 x y
Function: mod0 x y
Function: div0-and-mod0 x y

[R6RS] これらはR6RSで導入された整数除算手続きです。 quotient, modulo, remainderと違い、 これらの手続きは整数でない値を取ることもできます。 被除数xには任意の実数、除数yにはゼロ以外の実数が許されます。

divは整数nを、modは実数mを返し、 それらは以下の関係を満たします。

例:

(div 123 10)     ⇒ 12
(mod 123 10)     ⇒ 3

(div 123 -10)    ⇒ -12
(mod 123 -10)    ⇒ 3

(div -123 10)    ⇒ -13
(mod -123 10)    ⇒ 7

(div -123 -10)   ⇒ 13
(mod -123 -10)   ⇒ 7

(div 123/7 10/9) ⇒ 15
(mod 123/7 10/9) ⇒ 19/21
;; 123/7 = 10/9 * 15 + 19/21

(div 14.625 3.75) ⇒ 3.0
(mod 14.625 3.75) ⇒ 3.375
;; 14.625 = 3.75 * 3.0 + 3.375

xが非負の整数、yが整数である場合は、 divmodの結果はquotientremainder の結果に一致します。しかしxが負になると結果は異なります。

div-and-moddivmodを同時に計算し、 結果を二つの値で返します。

div0mod0は、mの値域が異なる以外は同じです。

(div0 123 10)   ⇒ 12
(mod0 123 10)   ⇒ 3

(div0 127 10)   ⇒ 13
(mod0 127 10)   ⇒ -3

(div0 127 -10)  ⇒ -13
(mod0 127 -10)  ⇒ -3

(div0 -127 10)  ⇒ -13
(mod0 -127 10)  ⇒ 3

(div0 -127 -10) ⇒ 13
(mod0 -127 -10) ⇒ 3

div0-and-mod0div0mod0を同時に計算し、 結果を二つの値で返します。

R6RSとR7RSの除算・剰余操作を可視化したものが http://blog.practical-scheme.net/gauche/20100618-integer-divisions にあります。

Function: gcd n …
Function: lcm n …

[R7RS] 与えられた整数の、最大公約数と最小公倍数をそれぞれ返します。

引数は整数でなければなりませんが、正確数である必要はありません。 引数が一つでも非正確なら、結果は非正確数になります。

Function: continued-fraction x

有限の実数xの正規連分数展開を、遅延シーケンスで返します。 xが無限大、NaN、または非実数の場合はエラーが報告されます。 返り値は遅延シーケンスなので、係数は必要になる度に計算されます。

(continued-fraction 13579/2468)
  ⇒ (5 1 1 122 1 9)

(+ 5 (/ (+ 1 (/ (+ 1 (/ (+ 122 (/ (+ 1 (/ 9))))))))))
  ⇒ 13579/2468

(continued-fraction (exact 3.141592653589793))
  ⇒ (3 7 15 1 292 1 1 1 2 1 3 1 14 3 3 2 1 3 3 7 2 1 1 3 2 42 2)

(continued-fraction 1.5625)
  ⇒ (1.0 1.0 1.0 3.0 2.0)
Function: numerator q
Function: denominator q

[R7RS] 有理数qの分子と分母をそれぞれ返します。

Function: rationalize x ebound

[R7RS] 実数xを、誤差ebound以内で近似した最も単純な有理数qを返します。

Gaucheは不正確な有理数をサポートしないので、引数の少なくとも一方が不正確数だと 結果の有理数が浮動小数点数へと変換され不正確数として返されることに注意してください。

(rationalize 1234/5678 1/1000) ⇒ 5/23

(rationalize 3.141592653589793 1/10000)
  ⇒ 3.141509433962264
(rationalize (exact 3.141592653589793) 1/10000)
  ⇒ 333/106
(rationalize (exact 3.141592653589793) 1/10000000)
  ⇒ 75948/24175

;; Some edge cases
(rationalize 2 +inf.0) ⇒ 0
(rationalize +inf.0 0) ⇒ +inf.0
(rationalize +inf.0 +inf.0) ⇒ +nan.0
Function: floor x
Function: ceiling x
Function: truncate x
Function: round x

[R7RS] 引数xは実数でなければなりません。floorceilingはそれぞれ xを越えない最大の整数と、xを下回らない最小の整数を返します。 truncatexの小数部をゼロの方向に向かって切捨てた整数を返します。 roundxに最も近い整数を返します。xの 小数部が0.5ぴったりだった場合はroundは最も近い偶数を返します。

Schemeの一般的な規則に従い、xが不正確数であれば結果も不正確となります。 例えば(round 2.3)の結果は2.0です。 もし、不正確な数を丸めて正確な整数を得たいのであれば、結果にexactを 適用するか、以下に示すfloor->exactなどの手続きを使ってください。

Function: floor->exact x
Function: ceiling->exact x
Function: truncate->exact x
Function: round->exact x

これらは、頻出する(exact (floor x)) 等を簡潔に書くための 手続きです。

Function: clamp x :optional min max
 min if x < min
 x   if min <= x <= max
 max if max < x

を返します。もしminまたはmaxが省略されるか#fが与えられたら、 それぞれ -∞ もしくは +∞ と解釈されます。 与えられた全ての数値が正確な整数の場合に限り正確な整数を返します。

(clamp 3.1 0.0 1.0) ⇒ 1.0
(clamp 0.5 0.0 1.0) ⇒ 0.5
(clamp -0.3 0.0 1.0) ⇒ 0.0
(clamp -5 0)        ⇒ 0
(clamp 3724 #f 256) ⇒ 256
Function: exp z
Function: log z
Function: log z1 z2
Function: sin z
Function: cos z
Function: tan z
Function: asin z
Function: acos z
Function: atan z
Function: atan y x

[R7RS] 超越関数です。複素数も扱えます。 R7RSではこれらの手続きは(scheme inexact)モジュールにあります。

2引数のlogはR6RSで追加されたもので、z2を底としたz1の対数を 返します。

2引数のatanは 実数xyに対して (angle (make-rectangular x y))を返します。

Function: sinh z
Function: cosh z
Function: tanh z
Function: asinh z
Function: acosh z
Function: atanh z

双曲線関数です。複素数も扱えます。

Function: sqrt z

[R7RS] 複素数zの平方根のひとつを返します。枝刈りの定義はCommon Lispと同じです。 実数に対しては正の平方根を返します。

zが正確な実数の平方である場合、戻り値は正確数となります。

(sqrt 2)      ⇒ 1.4142135623730951
(sqrt -2)     ⇒ 0.0+1.4142135623730951i
(sqrt 256)    ⇒ 16
(sqrt 256.0)  ⇒ 16.0
(sqrt 81/169) ⇒ 9/13
Function: exact-integer-sqrt k

[R7RS] 非負の正確な整数kに対し、次の式を満たす 非負の正確な整数srを返します。

k = (+ (* s s) r)
k < (* (+ s 1) (+ s 1))
(exact-integer-sqrt 782763574)
  ⇒ 27977 and 51045
Function: expt z1 z2

[R7RS] 複素数z1, z2に対して、 z1^z2 (z1z2乗)を返します。

Function: expt-mod base exponent mod

(modulo (expt base exponent) mod) を効率よく計算します。

次の例は、メルセンヌ素数M_74207281 (2^74207281 - 1) の最後の10桁を 求めます。

(- (expt-mod 2 74207281 #e1e10) 1)
 ⇒ 1086436351
Function: gamma x
Function: lgamma x

ガンマ関数と、ガンマ関数の絶対値の自然対数です。

註:数学的にはこれらの関数は複素領域で定義されますが、現在の実装は実数引数だけを サポートします。

Function: fixnum-width
Function: greatest-fixnum
Function: least-fixnum

[R6RS] これらの手続きは、fixnumで表現できる数値の幅 (wとします)、 fixnumで表現できる最大の整数値 (2^(w-1) - 1)、および fixnumで表現できる最小の整数値 (- 2^(w-1)) を それぞれ返します。性能が重要になる部分では数値がfixnumの範囲に収まるかどうかを 気にかける必要があります。

これらの名前はR6RSで定義されました。Common LispとChezSchemeには most-positive-fixnumおよびmost-negative-fixnumがあります。

註: 0.9.5以前のfixnum-widthには本来より1小さい値を返すバグがありました。


Next: , Previous: , Up: 数値   [Contents][Index]

6.3.5 数値の変換

Function: make-rectangular x1 x2
Function: make-polar x1 x2

[R7RS] 二つの実数x1x2から複素数を作ります。 make-rectangularx1 + ix2 を返します。 make-polarx1e^(ix2) を返します。

R7RSではこれらの手続きは(scheme complex)ライブラリにあります。

Function: real-part z
Function: imag-part z
Function: magnitude z
Function: angle z

[R7RS] 複素数zを取り、実数を返します。 real-partimag-partzの実数部と虚数部をそれぞれ返し、 magnitudeanglezの絶対値と偏角をそれぞれ返します。

R7RSではこれらの手続きは(scheme complex)ライブラリにあります。

Function: decode-float x

与えられた有限の浮動小数点数xに対して、 3つの正確な整数からなるベクタ #(m, e, sign) を返します。ここで、

  x = (* sign m (expt 2.0 e))
  sign は 1, 0 または -1.

です。

特例として、x+inf.0もしくは-inf.0の時は m#tに、 x+nan.0の時はm#fになります。

このAPIはChezSchemeから取られました。

(decode-float 3.1415926)
 ⇒ #(7074237631354954 -51 1)
(* 7074237631354954 (expt 2.0 -51))
 ⇒ 3.1415926

(decode-float +nan.0)
 ⇒ #(#f 0 -1)
Function: encode-float vector

これはdecode-floatの逆関数です。vectordecode-floatが返す形式の3要素のベクタでなければなりません。

(encode-float '#(7074237631354954 -51 1))
 ⇒ 3.1415926

(encode-float '#(#t 0 1))
 ⇒ +inf.0
Function: fmod x y
Function: modf x
Function: frexp x
Function: ldexp x n

[POSIX] これらの手続きは、浮動小数点数を分解したり合成するのに使えます。 fmodは実数xを実数yで割った余りを返します。すなわち、 x/yを0に近いほうの整数に丸めた値をnとするとき、 x-n*yを返します。 modfxの少数部と整数部を返します。 frexpは実数xを、仮数部と指数部に分解して返します。すなわち、 xが0でない限り、 x = fraction * 2^exponent かつ 0.5 <= |fraction| < 1.0 であるところのfractionexponentを返します。 (xが0であれば、fractionexponentはともに0となります。) ldexpfrexpの逆関数で、x * 2^n を返します。

(fmod 32.1 10.0)  ⇒ 2.1
(fmod 1.5 1.4)    ⇒ 0.1
(modf 12.5)       ⇒ 0.5 and 12.0
(frexp 3.14)      ⇒ 0.785 and 2
(ldexp 0.785 2)   ⇒ 3.14
Function: exact z
Function: inexact z

[R7RS] それぞれ数zの正確な表現および不正確な表現を返します。 正確数をexactに渡した場合や、不正確数をinexactに渡した場合は 渡した値がそのまま返されます。

Gaucheは、虚部がゼロでない正確な複素数や、正確な無限大/NaNをサポートしないので、 これらの数がexactに渡された場合はエラーとなります。

(inexact 1)    ⇒ 1.0
(inexact 1/10) ⇒ 0.1

不正確で有限な実数がexactに渡された場合は、 浮動小数点数演算の精度の中で最も簡単な表現となる正確な有理数が返されます。

(exact 1.0)     ⇒ 1
(exact 0.1)     ⇒ 1/10
(exact (/ 3.0)) ⇒ 1/3

あらゆる有限の不正確な実数xについて、 (inexact (exact x)) は常に元の数xeqv?になります。

(その逆、つまり正確数 n(exact (inexact n)) は 必ずしも等しくならないことに注意してください。 ある不正確数へと写像される正確数は無数にあり得るためです。)

誤差の許容範囲を指定して非正確な実数を正確な有理数に直したい場合は、 rationalizeおよびreal->rationalを参照してください。

Function: exact->inexact z
Function: inexact->exact z

[R5RS] それぞれ、正確数を非正確に変換、あるいはその逆を行います。

不正確な数をexact->inexactに渡したり、または正確な数を inexact->exactに渡した場合、Gaucheではそれをエラーにせず 引数をそのまま返します。従ってこれらはGaucheでは 上のinexactおよびexactとそれぞれ等価です。 R5RS実装の中には、非正確数をexact->inexactに渡したりすると エラーになるものもあり得るので、ポータブルなコードを書く場合は 注意してください。

一般的には、exactおよびinexactを使う方が 簡潔で良いでしょう。こちらの手続きはR5RSプログラムとの互換性の ために用意されています。

Function: real->rational x :optional hi lo open?

指定されたエラー範囲の中で、有限な実数xの正確な有理数表現のうち 最も簡単なものを返します。ratinalizeexactはこの手続きを 下請けとして呼び出しています。

返される有理数は次の条件を満たします。

(<= (- x lo) r (+ x hi))   ; when open? is #f
(<  (- x lo) r (+ x hi))   ; otherwise

hiloは非負でなければなりません。

hiloの両方、もしくは一方が省略された場合、それはxの値に応じて 決定されます。xが正確数の場合、省略されたhi/loはゼロとみなされます。 xが非正確数の場合は、xの浮動小数点数表現の精度に基づいて hi/loが決定されます。後者の場合、open?の値もまた、 xの値で決まります。浮動小数点数の「偶数丸め」規則に対応して、 xの仮数部が奇数であればopen?は真、そうでなければ偽となります。 従って、real->rationalにひとつの有限の数値だけを渡した場合、 その動作はexactと同じになります。

(real->rational 0.1) ⇒ 1/10

エラー範囲にゼロを渡すと、引数の浮動小数点数の正確な数値表現 (つまり、(* sign mantissa (expt 2 exponent))を正確値で計算した結果) が返されます。

(real->rational 0.1 0 0) ⇒ 3602879701896397/36028797018963968

(hilo引数を与えて open?を省略した場合は、 閉じた範囲と考えます。)

Function: number->string z :optional radix use-upper?
Function: string->number string :optional radix

[R7RS+] これらの手続きは数値とそれをradix進数で表現する文字列とを変換します。 radixは2から36の間でなければなりません。省略された場合は10進数とみなされます。

number->stringは数値zを取り文字列を返します。 zが正確な整数以外の場合、radixは10でなければなりません。 10より大きいradixに関しては、小文字のアルファベットが桁として使われます。 但し、省略可能な引数use-upper?に真の値が与えられた場合は大文字のアルファベットが 使われます。use-upper?引数はGaucheの拡張です。

string->numberは文字列stringを取り数値を返します。 不正確な数値は10進数表記しか認識されません。与えられた文字列が数値を構成しない 場合は#fが返されます。

Generic Function: x->number obj
Generic Function: x->integer obj

数値への強制型変換手続きです。 objをそれぞれ数値もしくは正確な整数と解釈して返します。 数値と文字列に対してのメソッドは定義されています (文字列はstring->numberを使って変換されます。 数値として解釈できない文字列に関しては0が返されます)。 その他のobjについては単に0が返されます。 x->integerは、objが数値として表現できるけれど正確な整数では ない場合、roundinexact->exactによって正確な整数に変換します。

他のクラスはこのメソッドを定義することにより、独自の変換関数を提供することができます。


Next: , Previous: , Up: 数値   [Contents][Index]

6.3.6 ビット演算

これらの手続きは整数を半無限のビットベクタとして扱います。 正の整数の場合、数値の左側に無限に0が続いていると見倣されます。 負の整数の場合、数値は2の補数で表現され、左側に無限に1が続いていると見倣されます。

これらの操作の名前に関しては、Scheme界には大きく二つの流儀があります。 GaucheはSLIBの元々の“logical”モジュールに合わせました。 その起源はCommon Lispです。 もう一つの流儀では、arithmetic-shiftといった、より長く記述的な名前を使います。

SRFI-60 (see 整数に対するビット操作) は両方の流儀の名前を定義しており、 さらにいくつかの追加の手続きも用意しています。他のScheme向けに書かれた コードをGaucheに移植する際には有用でしょう。

Function: ash n count

[SRFI-60] 整数nを左に整数countビットだけシフトします。 countが負であれば、-countだけnを右にシフトします。

; Note: 6  ≡ [...00110], and
;       -6 ≡ [...11010]
(ash 6 2)   ⇒ 24  ;[...0011000]
(ash 6 -2)  ⇒ 1   ;[...0000001]
(ash -6 2)  ⇒ -24 ;[...1101000]
(ash -6 -2) ⇒ -2  ;[...1111110]
Function: logand n1 …
Function: logior n1 …
Function: logxor n1 …

[SRFI-60] 整数n1 …の、それぞれビット論理積、 ビット論理和、ビット排他的論理積を返します。 ゼロ個の引数が与えられた場合は、logand-1を、 logiorlogxor0を返します。

Function: lognot n

[SRFI-60] 整数nのビット否定を返します。

Function: logtest n1 n2 …

[SRFI-60] ≡ (not (zero? (logand n1 n2 …)))

Function: logbit? index n

[SRFI-60] 整数nindex目のビットが1ならば#tを、0ならば#fを 返します。

Function: bit-field n start end

[SRFI-60] 整数nstartビット目(含む)からendビット目(含まない)までを 取り出した数値を返します。start < end でなければなりません。

Function: copy-bit index n bit

[SRFI-60] bitが真の値なら、整数nindexビット目をセットした数値を 返します。 bitが偽の値なら、整数nindexビット目をリセットした数値を 返します。

Function: copy-bit-field n from start end

[SRFI-60] 正確な整数を返します。この整数の各ビットはstart番目のビット(この ビットを含む)からend番目のビット(このビットは含まない)の部分以外 はnと同じで、この区間のビットは、正確な数fromの下位 (end-start)ビットのコピーです。

(number->string (copy-bit-field #b10000000 -1 1 5) 2)
  ⇒ "10011110"

(number->string (copy-bit-field #b10000000 #b010101010 1 7) 2)
  ⇒ "11010100"

註:この手続きのAPIはSLIBから採られましたが、採用当時の引数の順序は (copy-bit-field n start end from) でした。SRFI-60の 議論中に、一貫性のために引数順が変更され、SLIBの新しいバージョンも それに追従しています。Gaucheではこの引数順の変更に最近まで気づいていなかったため、 0.9.4以前のバージョンではcopy-bit-fieldが古い引数順で定義されています。 この手続きを使っていたコードは0.9.4以降のGaucheで使う際に修正しなければなりません。 もしどちらのバージョンのGaucheでも動かす必要がある場合は、 回避策としてcopy-bit-fieldの定義を自前で持つのが良いでしょう。

(define (copy-bit-field to from start end)
  (if (< start end)
    (let1 mask (- (ash 1 (- end start)) 1)
      (logior (logand to (lognot (ash mask start)))
              (ash (logand from mask) start)))
    from))
Function: logcount n

[SRFI-60] nが正なら、nのビットのうち1の個数を返します。n が負なら、nの2に関する補数のビットのうち0の個数を返します。

(logcount 0)      ⇒ 0
(logcount #b0010) ⇒ 1
(logcount #b0110) ⇒ 2
(logcount #b1111) ⇒ 4

(logcount #b-0001) ⇒ 0  ;; 2の補数:  ....111111
(logcount #b-0010) ⇒ 1  ;; 2の補数:  ....111110
(logcount #b-0011) ⇒ 1  ;; 2の補数:  ....111101
(logcount #b-0100) ⇒ 2  ;; 2の補数:  ....111100
Function: integer-length n

[SRFI-60] 正確な整数nを表現するのに必要な最小ビット数を返します。負の数は2 の補数で表現されるものと仮定しています。符号用のビットは考慮しません。

(integer-length 255)  ⇒ 8
(integer-length 256)  ⇒ 9

(integer-length -256)  ⇒ 8
(integer-length -257)  ⇒ 9
Function: twos-exponent n

nが2の冪乗(expt 2 k) (k >= 0) ならその冪 k を、 そうでなければ#fを返します。

Function: twos-exponent-factor n

(expt 2 k)nの約数であるような最大のkを返します。 言い換えれば、nのLSBから連続するゼロビットの数を返します。 ただしnがゼロならゼロを返します。

これは次の式でも計算できますが、この手続きはnがbignumの場合にも 中間結果を作らないので若干速いです。

(- (integer-length (logxor n (- n 1))) 1)

Previous: , Up: 数値   [Contents][Index]

6.3.7 エンディアン

Schemeの世界では、数値がマシン上でどのように表現されているかを気にする 必要はほとんどありません。しかし、外の世界とバイナリ表現でデータを やりとりする場合はそれが問題になります。

binary.ioモジュール(バイナリI/O参照)や write-uvector/read-uvector!(ユニフォームベクタ参照) 等、Gaucheのバイナリ入出力手続きはエンディアンを指定する 省略可能なendian引数を取ります。

エンディアンの指定には次のシンボルを使います。

big-endian

ビッグエンディアン。32ビット整数値#x12345678#x12 #x34 #x56 #x78 のようなバイトシーケンスとして出力されます。

little-endian

リトルエンディアン。32ビット整数値#x12345678#x78 #x56 #x34 #x12 のようなバイトシーケンスとして出力されます。

arm-little-endian

これはlittle-endianのバリエーションで、ARMプロセッサの 特定のモードで使われるものです。倍精度浮動小数点数以外はlittle-endian と同様に動作します。倍精度浮動小数点数については、ふたつのリトルエンディアンワードが ビッグエンディアンの順で書き出されます (例えばマシンレジスタ上でのビットパターンが #x0102030405060708の場合、出力は #x04 #x03 #x02 #x01 #x08 #x07 #x06 #x05となります)。

endian引数が省略された場合は、これらの手続きはパラメータdefault-endianの 値を使います。

Parameter: default-endian

これは、バイナリ入出力ルーチンでendian指定が省略された場合に 共通して使われるエンディアンを指定する動的パラメータです (パラメータ参照)。 このパラメータの初期値はシステムのネイティブエンディアンです。

システムのネイティブエンディアンは次の手続きで得られます。

Function: native-endian

システムのエンディアンを示すシンボルを返します。


Previous: , Up: 数値   [Contents][Index]