For Development HEAD DRAFTSearch (procedure/syntax/module):

6.3 数値

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

多倍長の正確な整数

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

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

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

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

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

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

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


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>>

6.3.2 数値に関する述語

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

[R7RS base] 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 base] 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 base] (and (exact? obj) (integer? obj))と等価ですが、より高速です。

Function: zero? z

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

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

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

マイナスゼロ(-0.0)はゼロであって負ではないことに注意してください。

Function: negative-zero? x

数値xがマイナスゼロ(-0.0)の場合に#tを、 そうでなければ#fを返します。xが数値でなければエラーが投げられます。

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

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

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

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

Function: odd? n
Function: even? n

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

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

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

fixnumを扱う包括的なライブラリはscheme.fixnum - R7RS fixnumを参照してください。

Function: flonum? x

[R7RS flonum] xが浮動小数点数で表現される数値の場合に#tを、それ以外の場合に #fを返します。Gaucheでは、非正確な実数がflonumです。

flonumを扱う包括的なライブラリはscheme.flonum - R7RS flonumを参照してください。

Function: ratnum? x

xが正確な非整数の場合に#tを、そうでなければ#fを返します。 この述語に#tを返す数値は内部的には二つの正確な整数の組で表現されています。

通常、正確な整数とratnumとを区別する必要はありません。両方とも単なる正確数です。 ただ、性能が要求されるコードにおいて、ratnumの演算が入ると計算が重くなるので、 その状況を検出したい場合はあるかもしれません。


6.3.3 数値の比較

Function: = z1 z2 z3 …

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

(= 2 2)          ⇒ #t
(= 2 3)          ⇒ #f
(= 2/4 1/2)      ⇒ #t

正確性は数値としての比較には影響しません。非正確な1.0と正確な1は=とみなされます。 非正確な正のゼロ(0.0)と非正確な負のゼロも=です。 それらを区別するには、eqv?equal?を使ってください。

(= 2 2.0)        ⇒ #t
(= 2 2.0 2.0+0i) ⇒ #t
(= -0.0 0.0)     ⇒ #t

;; cf:
(eqv? 2 2.0)     ⇒ #f
(eqv? -0.0 0.0)  ⇒ #f

+nan.0は、それ自身を含めていかなる数値とも=になりません。

(= +nan.0 +inf.0)  ⇒ #f
(= +nan.0 +nan.0)  ⇒ #f

(let ((x +nan.0)) (= x x)) ⇒ #f
Function: < x1 x2 x3 …
Function: <= x1 x2 x3 …
Function: > x1 x2 x3 …
Function: >= x1 x2 x3 …

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

(= 0.0 -0.0)#tなので、(> 0.0 -0.0)#fになります。

引数にNaNが入っていると結果は#fになります。 すなわち、(< x y) ⇒ #fだからといって(>= x y) ⇒ #t とは限りません。

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

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

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

Function: min&max x1 x2 …

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

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

Function: approx=? x y :optional relative-tolerance absolute-tolerance

二つの数値が与えられたエラー許容範囲内で等しいとみなせる場合に#tを、 そうでなければ#fを返します。

  • xyの少なくとも一方がNaNであれば、常に#fを返します。
  • 一方が無限大である場合、もう一方も同じ符号の無限大である場合のみ#tを、 そうでなければ#fを返します。
  • そうでない場合、次の式により一致が判定されます。
    (<= (abs (- x y))
        (max (* (max (abs x) (abs y)) relative-tolerance)
             absolute-tolerance))
    

xyの少なくとも一方が非実数の複素数である場合は、 absのかわりにmagnitudeが使われます。

省略された場合、relative-toleranceには (flonum-epsilon)の値が、absolute-toleranceには (least-positive-flonum)の値が使われます。 すなわち、デフォルトではapprox=?は 1 ULP (unit in the last place)のエラーを許容するということです。

absolute-tolerance引数は、引数がともにゼロに近く、 相対許容範囲が小さくなりすぎる場合に便利です。

Function: flonum-epsilon
Function: greatest-positive-flonum
Function: least-positive-flonum
Function: least-positive-normalized-flonum

それぞれ次の性質を持つ浮動小数点数を返します:

flonum-epsilon

正規化浮動小数点数xに対し、x(* x (+ 1.0 e))が 異なる値となるような最小の正の浮動小数点数。

greatest-positive-flonum

有限な最大の正の浮動小数点数。Cで言うところのDBL_MAX

least-positive-flonum

最小の正の浮動小数点数。 プラットフォームが非正規化浮動小数点数をサポートしている場合は最小の 正の非正規化浮動小数点数が、そうでなければ 最小の正の正規化浮動小数点数が返ります。

least-positive-normalized-flonum

最小の正の正規化浮動小数点数。

註: ポータブルなプログラムは、R7RSのscheme.flonumが提供する 定数fl-epsilonfl-greatestfl-leastを 使うことができます (scheme.flonum - R7RS flonum参照)。

Function: flonum-min-normalized
Function: flonum-min-denormalized

Deprecated. これらはleast-positive-normalized-flonumおよび least-positive-flonumの旧い名前です。 意味を明確にするために名前を変えました。

  • 新しい名前はleast-fixnum/greatest-fixnumと統一性があります。
  • minleastだけだと、ゼロから負の方向に一番離れている数の意味にも 取れるので、positiveをつけて曖昧性を排除しました。
  • 非正規化浮動小数点数はサポートされていないプラットフォームがあり得るので、 名前にdenormalizedを入れるのを避けました。

6.3.4 数値の演算

Function: + z …
Function: * z …

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

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

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

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

z1 - z2 - z3 ...
z1 / 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+ base] 実数の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 base] 整数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を返し、 それらは以下の関係を満たします。

  • x = n y + m
  • 0 <= m < |y|

例:

(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の値域が異なる以外は同じです。

  • x = n y + m
  • -|y|/2 <= m < |y|/2
(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: floor-quotient n d
Function: floor-remainder n d
Function: floor/ n d
Function: truncate-quotient n d
Function: truncate-remainder n d
Function: truncate/ n d

[R7RS base] R7RSで導入された整数除算オペレータです。除数や被除数が負の場合の振る舞いが、 名前によって明示されています。

引数ndは整数でなけばなりません。 両方とも正確数であれば結果は正確数に、一方でも非正確数であれば 結果は非正確数になります。また、dはゼロであってはなりません。

被除数n、除数d、商q、剰余rには常に以下の関係が成り立ちます。

r = n - dq
abs(r) < abs(d)

(floor-quotient n d)(truncate-quotient n d)はそれぞれ (floor (/ n d))(truncate (/ n d))と同じです。 対応する*-remainderは、上記の関係から導かれます。

floor/truncate/は、対応する商と剰余を二つの値として返します。

(floor-quotient 10 -3)     ⇒ -4
(floor-remainder 10 -3)    ⇒ -2
(truncate-quotient 10 -3)  ⇒ -3
(truncate-remainder 10 -3) ⇒ 1

R7RS除算ライブラリ(scheme.division)では、 他の整数除算のバリエーションが定義されています。 (scheme.division - R7RS整数除算参照)。

Function: gcd n …
Function: lcm n …

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

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

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 base] 有理数qの分子と分母をそれぞれ返します。

Function: rationalize x ebound

[R7RS base] 実数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 base] 引数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 inexact] 超越関数です。複素数も扱えます。 R7RSではこれらの手続きは(scheme inexact)モジュールにあります。

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

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

実数に限定したこれらの関数については、下のreal-exp等も参照してください。

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

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

実数に限定したこれらの関数については、下のreal-sinh等も参照してください。

Function: radians->degrees rad
Function: degrees->radians deg

ラジアンと度を変換します。引数は実数でなければなりません。

Function: sqrt z

[R7RS inexact] 複素数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

不正確な実数に限定したsqrtについては、下のreal-sqrtも参照してください。

Function: exact-integer-sqrt k

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

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

[R7RS base] (* z z)を返します。

Function: expt z1 z2

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

Scheme標準では便宜上(expt 0 0)は1と定めています。

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: real-exp x
Function: real-expt x y
Function: real-ln x
Function: real-sqrt x
Function: real-sin x
Function: real-cos x
Function: real-tan x
Function: real-asin x
Function: real-acos x
Function: real-atan x
Function: real-atan y x

[SRFI-94] 実数の範囲に限定した初等関数です。引数が実数でなかったらエラーが投げられます。

性能を気にするコードでは有用です。複素数の処理のためのチェックが省かれるのと、 定数畳み込みが行われやすくなります。

これらの名前はSRFI-94で定義されています。ただ、今ポータブルなコードを書きたいなら、 R7RS-largeの一部であるscheme.flonumを使う方が良いでしょう。 そこではflonum限定の初等関数が定義されています(scheme.flonum - R7RS flonum参照)。

註:SRFI-94は実数限定の2引数のlogであるreal-logも定義しているのですが、 対数の底を最初の引数に取るようになっていて、R7RSのlogとは逆です。 混乱を避けるため、コアではreal-logは提供していません。

Function: real-sinpi x
Function: real-cospi x
Function: real-tanpi x

それぞれsin(πx)、cos(πx)、tan(πx)を返します。 引数が実数でなければエラーを投げます。 下の例が示すように、これらはしばしば便利です:

(use math.const)
(real-sin pi)     ⇒ 1.2246467991473532e-16
(real-sinpi 1.0)  ⇒ 0.0

(real-cos (/ pi 2)) ⇒ 6.123233995736766e-17
(real-cospi 0.5)    ⇒ 0.0
Function: real-sinh x
Function: real-cosh x
Function: real-tanh x
Function: real-asinh x
Function: real-acosh x
Function: real-atanh x

実数限定の双曲線関数とその逆関数です。 引数が実数でなければエラーが投げられます。

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小さい値を返すバグがありました。


6.3.5 数値の変換

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

[R7RS complex] 二つの実数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 complex] 複素数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 base] それぞれ数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の正確な有理数表現のうち 最も簡単なものを返します。rationalizeexactはこの手続きを 下請けとして呼び出しています。通常はrationalize (数値の演算参照) を使い、real->rationalは誤差許容値をより細かく制御したい時のみ 使うのが良いでしょう。

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

(<= (- 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 default-exactness

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

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

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

string->numberの省略可能引数default-exactnessはGaucheの拡張で、 #f (デフォルト)あるいはシンボルexactまたはinexactの いずれかでなければなりません。 シンボルが与えられた場合は、正確数か非正確数かがプレフィクス(#eもしくは#i) で明示されていない場合の正確性の解釈を指定します。 文字列に正確性のプレフィクスがついていた場合はdefault-exactness の指定は無視されます。

(string->number "2.718281828459045" 10 'exact)
  ⇒ 543656365691809/200000000000000
(string->number "#i2.718281828459045" 10 'exact)
  ⇒ 2.718281828459045
(string->number "1/3" 10 'inexact)
  ⇒ 0.3333333333333333
(string->number "#e1/3" 10 'inexact)
  ⇒ 1/3
Generic Function: x->number obj
Generic Function: x->integer obj

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

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


6.3.6 基本的なビット演算

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

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

R7RSビット演算ライブラリ(see scheme.bitwise - R7RSビット演算) は追加のビット演算を提供しています。

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: logset+clear n set-bits clear-bits

nのビットのうち、set-bitsで1が立っているビットを立て、 clear-bitsで1が立っているビットをクリアした整数を返します。

実質的に(logand (logior n set-bits) (lognot clear-bits))と同じです。

(logset+clear #b11000011 #b00001100 #b01000001)
  ⇒ 142  ;; #b10001110
Function: bit-field n start end

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

Function: copy-bit index n bit

[R7RS bitwise] 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

[R7RS bitwise] 正確な整数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がゼロの場合は、下の等価式との一貫性から-1が返されます。

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

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

この手続きはまた、SRFI-60のlog2-binary-factorsおよび first-set-bitと等価です(srfi.60 - 整数に対するビット操作参照)。


6.3.7 エンディアンネス

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

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

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

big-endian
big

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

Gaucheはずっとbig-endianを使ってきましたが、 R7RS-largeに取り入れられたscheme.bytevectorbigを使うので、 両方認識するようになっています。

little-endian
little

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

Gaucheはずっとlittle-endianを使ってきましたが、 R7RS-largeに取り入れられたscheme.bytevectorlittleを使うので、 両方認識するようになっています。

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

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



For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT