Gaucheは次のタイプの数値をサポートしています。
メモリの許す限りの精度が扱えます。
分母と分子は正確な整数で表現されます。 メモリの許す限りの精度が扱えます。
実装に使われるC言語のdouble
型で表現されます。通常IEEE 64bit浮動小数点数です。
実部と虚部はそれぞれ浮動小数点の非正確な実数で表現されます。
• 数値クラス: | ||
• 数値に関する述語: | ||
• 数値の比較: | ||
• 数値の演算: | ||
• 数値の変換: | ||
• 基本的なビット演算: | ||
• エンディアンネス: |
数値オブジェクトのクラス階層を構成します。<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>>
[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
であることを当てにしているものは
うまく動かないでしょう。
[R6RS]
Gaucheではこれらの手続きはそれぞれreal?
、rational?
、
およびinteger?
の別名となっています。これらはR6RSコードとの互換性のために
提供されています。
R6RSで規定されている、これらの手続きと-valued
がついていない手続きの違いは、
これらの手続きは非正確なゼロの虚部を持つ複素数に対しても#t
を返すという
ことです。Gaucheではゼロの虚部を持つ複素数は実数とみなしているので、
この違いは現れません。
[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
[R7RS base]
(and (exact? obj) (integer? obj))
と等価ですが、より高速です。
[R7RS base]
数値zがゼロに等しければ#t
を返します。
(zero? 1) ⇒ #f (zero? 0) ⇒ #t (zero? 0.0) ⇒ #t (zero? -0.0) ⇒ #t (zero? 0.0+0.0i) ⇒ #t
[R7RS base]
実数xがそれぞれ正または負なら#t
を返します。
非実数を渡すとエラーになります。
マイナスゼロ(-0.0
)はゼロであって負ではないことに注意してください。
数値xがマイナスゼロ(-0.0
)の場合に#t
を、
そうでなければ#f
を返します。xが数値でなければエラーが投げられます。
[R7RS inexact]
実数に対して、それが有限、無限、NaNであればそれぞれ#t
を返します。
非実数の複素数に対しては、finite?
は実数部と仮数部がともに
有限なら#t
を、infinite?
は実数部と仮数部の少なくともどちらかが
無限なら#t
を、nan?
は実数部と仮数部の少なくともどちらかが
NaNなら#t
を返します。(これはR6RSとは非互換です。R6RSでは
これらの手続きは引数に非実数の数が与えられた場合はエラーを通知しなければならないからです。)
R7RSではこれらの手続きは(scheme inexact)
ライブラリにあります。
[R7RS base]
整数nがそれぞれ奇数または偶数なら#t
を返します。
非整数を渡すとエラーになります。
(odd? 3) ⇒ #t (even? 3) ⇒ #f (odd? 3.0) ⇒ #t
[R7RS fixnum]
nが正確な整数で、かつ内部的にそれぞれfixnumもしくはbignum
で表現されているときに#t
を返します。R7RS-largeは
scheme.fixnum
ライブラリでfixnum?
を定義しています。
bignum?
はGauche拡張です。
通常のSchemeプログラムは整数の内部表現を気にする必要はありません。
これらの手続きは、ある種の最適化を行う低レベル手続きのために用意されています。
fixnumを扱う包括的なライブラリはscheme.fixnum
- R7RS fixnumを参照してください。
[R7RS flonum]
xが浮動小数点数で表現される数値の場合に#t
を、それ以外の場合に
#f
を返します。Gaucheでは、非正確な実数がflonumです。
flonumを扱う包括的なライブラリはscheme.flonum
- R7RS flonumを参照してください。
xが正確な非整数の場合に#t
を、そうでなければ#f
を返します。
この述語に#t
を返す数値は内部的には二つの正確な整数の組で表現されています。
通常、正確な整数とratnumとを区別する必要はありません。両方とも単なる正確数です。 ただ、性能が要求されるコードにおいて、ratnumの演算が入ると計算が重くなるので、 その状況を検出したい場合はあるかもしれません。
[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
[R7RS base]
与えられた全ての実数xがそれぞれ単調増加、単調非減少、単調減少、単調非増加している
場合に#t
を返します。
(= 0.0 -0.0)
は#t
なので、(> 0.0 -0.0)
は#f
になります。
引数にNaNが入っていると結果は#f
になります。
すなわち、(< x y) ⇒ #f
だからといって(>= x y) ⇒ #t
とは限りません。
[R7RS base] 与えられた実数のうち、それぞれ最大と最小のものを返します。 引数にNaNが含まれていた場合は、NaNが返されます。
コレクションからの選択と探索の
find-min
とfind-max
も参照。
与えられた実数から、最大値と最小値の二つの値を返します。
コレクションからの選択と探索の
find-min&max
も参照。
二つの数値が与えられたエラー許容範囲内で等しいとみなせる場合に#t
を、
そうでなければ#f
を返します。
#f
を返します。
#t
を、
そうでなければ#f
を返します。
(<= (abs (- x y)) (max (* (max (abs x) (abs y)) relative-tolerance) absolute-tolerance))
xかyの少なくとも一方が非実数の複素数である場合は、
abs
のかわりにmagnitude
が使われます。
省略された場合、relative-tolerance
には
(flonum-epsilon)
の値が、absolute-toleranceには
(least-positive-flonum)
の値が使われます。
すなわち、デフォルトではapprox=?
は
1 ULP (unit in the last place)のエラーを許容するということです。
absolute-tolerance引数は、引数がともにゼロに近く、 相対許容範囲が小さくなりすぎる場合に便利です。
それぞれ次の性質を持つ浮動小数点数を返します:
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-epsilon
、fl-greatest
、fl-least
を
使うことができます (scheme.flonum
- R7RS flonum参照)。
Deprecated.
これらはleast-positive-normalized-flonum
および
least-positive-flonum
の旧い名前です。
意味を明確にするために名前を変えました。
least-fixnum
/greatest-fixnum
と統一性があります。
[R7RS base]
与えられた数の和と積をそれぞれ返します。引数が与えられない場合、
(+)
は 0、 (*)
は 1 となります。
[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のふるまいを当てにしていた場合、
速度が大きく低下する可能性があります。正確な有理数の演算は
浮動小数点数の演算よりはるかに遅いからです。
(正確な結果を得たいのでない場合は)下に述べる/.
を使うと良いでしょう。
+
、*
、-
、/
と同様ですが、引数は非正確な
数へと変換され、結果も常に非正確な数となります。
正確数による計算が不要で、bignumや正確な有理数をうっかり使ってしまう
ことによるオーバヘッドを避けたい時に便利です。
[R7RS+ base] 実数のzに対しては、その絶対値を返します。 複素数のzに対しては、そのmagnitudeを返します。 複素数を扱うのはGaucheの拡張です。
(abs -1) ⇒ 1 (abs -1.0) ⇒ 1.0 (abs 1+i) ⇒ 1.4142135623731
[R7RS base] 整数n1を整数n2で割った商(quotient)および余り(remainder, modulo) を返します。 n1とn2の両方が正確な数値の時のみ、戻り値は正確な数値になります。
remainder
とmodulo
はどちらかの引数が負の時に異なる値を返します。
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
整数n1を整数n2で割った商(quotient)および余り(remainder) を同時に計算し、2つの値として返します。
[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が整数である場合は、
div
とmod
の結果はquotient
とremainder
の結果に一致します。しかしxが負になると結果は異なります。
div-and-mod
はdiv
とmod
を同時に計算し、
結果を二つの値で返します。
div0とmod0は、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-mod0
はdiv0
とmod0
を同時に計算し、
結果を二つの値で返します。
R6RSとR7RSの除算・剰余操作を可視化したものが http://blog.practical-scheme.net/gauche/20100618-integer-divisions にあります。
[R7RS base] R7RSで導入された整数除算オペレータです。除数や被除数が負の場合の振る舞いが、 名前によって明示されています。
引数nとdは整数でなけばなりません。 両方とも正確数であれば結果は正確数に、一方でも非正確数であれば 結果は非正確数になります。また、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整数除算参照)。
[R7RS base] 与えられた整数の、最大公約数と最小公倍数をそれぞれ返します。
引数は整数でなければなりませんが、正確数である必要はありません。 引数が一つでも非正確なら、結果は非正確数になります。
有限の実数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)
[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
[R7RS base]
引数xは実数でなければなりません。floor
とceiling
はそれぞれ
xを越えない最大の整数と、xを下回らない最小の整数を返します。
truncate
はxの小数部をゼロの方向に向かって切捨てた整数を返します。
round
はxに最も近い整数を返します。xの
小数部が0.5ぴったりだった場合はround
は最も近い偶数を返します。
Schemeの一般的な規則に従い、xが非正確数であれば結果も非正確となります。
例えば(round 2.3)
の結果は2.0
です。
もし、非正確な数を丸めて正確な整数を得たいのであれば、結果にexact
を
適用するか、以下に示すfloor->exact
などの手続きを使ってください。
これらは、頻出する(exact (floor x))
等を簡潔に書くための
手続きです。
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
[R7RS inexact]
超越関数です。複素数も扱えます。
R7RSではこれらの手続きは(scheme inexact)
モジュールにあります。
exp
はeのz乗を返します。
1引数のlog
はzの自然対数を返します。
2引数のlog
はR6RSで追加されたもので、
z2を底としたz1の対数を返します。
2引数のatan
は
実数xとyに対して
(angle (make-rectangular x y))
を返します。
実数に限定したこれらの関数については、下のreal-exp
等も参照してください。
双曲線関数です。複素数も扱えます。
実数に限定したこれらの関数については、下のreal-sinh
等も参照してください。
[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
も参照してください。
[R7RS base] 非負の正確な整数kに対し、次の式を満たす 非負の正確な整数sとrを返します。
k = (+ (* s s) r) k < (* (+ s 1) (+ s 1))
(exact-integer-sqrt 782763574)
⇒ 27977 and 51045
[R7RS base]
(* z z)
を返します。
[R7RS base] 複素数z1, z2に対して、 z1^z2 (z1のz2乗)を返します。
Scheme標準では便宜上(expt 0 0)
は1と定めています。
(modulo (expt base exponent) mod)
を効率よく計算します。
次の例は、メルセンヌ素数M_74207281 (2^74207281 - 1) の最後の10桁を 求めます。
(- (expt-mod 2 74207281 #e1e10) 1) ⇒ 1086436351
[SRFI-94] 実数の範囲に限定した初等関数です。引数が実数でなかったらエラーが投げられます。
性能を気にするコードでは有用です。複素数の処理のためのチェックが省かれるのと、 定数畳み込みが行われやすくなります。
これらの名前はSRFI-94で定義されています。ただ、今ポータブルなコードを書きたいなら、
R7RS-largeの一部であるscheme.flonum
を使う方が良いでしょう。
そこではflonum限定の初等関数が定義されています(scheme.flonum
- R7RS flonum参照)。
註:SRFI-94は実数限定の2引数のlog
であるreal-log
も定義しているのですが、
対数の底を最初の引数に取るようになっていて、R7RSのlog
とは逆です。
混乱を避けるため、コアではreal-log
は提供していません。
それぞれ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
実数限定の双曲線関数とその逆関数です。 引数が実数でなければエラーが投げられます。
ガンマ関数と、ガンマ関数の絶対値の自然対数です。
註:数学的にはこれらの関数は複素領域で定義されますが、現在の実装は実数引数だけを サポートします。
[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小さい値を返すバグがありました。
[R7RS complex]
二つの実数x1とx2から複素数を作ります。
make-rectangular
は x1 + ix2 を返します。
make-polar
は x1e^(ix2) を返します。
R7RSではこれらの手続きは(scheme complex)
ライブラリにあります。
[R7RS complex]
複素数zを取り、実数を返します。
real-part
とimag-part
はzの実数部と虚数部をそれぞれ返し、
magnitude
とangle
はzの絶対値と偏角をそれぞれ返します。
R7RSではこれらの手続きは(scheme complex)
ライブラリにあります。
与えられた有限の浮動小数点数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)
これはdecode-float
の逆関数です。vectorは
decode-float
が返す形式の3要素のベクタでなければなりません。
(encode-float '#(7074237631354954 -51 1)) ⇒ 3.1415926 (encode-float '#(#t 0 1)) ⇒ +inf.0
[POSIX]
これらの手続きは、浮動小数点数を分解したり合成するのに使えます。
fmod
は実数xを実数yで割った余りを返します。すなわち、
x/yを0に近いほうの整数に丸めた値をnとするとき、
x-n*yを返します。
modf
はxの少数部と整数部を返します。
frexp
は実数xを、仮数部と指数部に分解して返します。すなわち、
xが0でない限り、
x = fraction * 2^exponent かつ 0.5 <= |fraction| < 1.0
であるところのfractionとexponentを返します。
(xが0であれば、fractionとexponentはともに0となります。)
ldexp
はfrexp
の逆関数で、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
[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))
は常に元の数xと
eqv?
になります。
(その逆、つまり正確数 n と (exact (inexact n))
は
必ずしも等しくならないことに注意してください。
ある非正確数へと写像される正確数は無数にあり得るためです。)
誤差の許容範囲を指定して非正確な実数を正確な有理数に直したい場合は、
rationalize
およびreal->rational
を参照してください。
[R5RS] それぞれ、正確数を非正確に変換、あるいはその逆を行います。
非正確な数をexact->inexact
に渡したり、または正確な数を
inexact->exact
に渡した場合、Gaucheではそれをエラーにせず
引数をそのまま返します。従ってこれらはGaucheでは
上のinexact
およびexact
とそれぞれ等価です。
R5RS実装の中には、非正確数をexact->inexact
に渡したりすると
エラーになるものもあり得るので、ポータブルなコードを書く場合は
注意してください。
一般的には、exact
およびinexact
を使う方が
簡潔で良いでしょう。こちらの手続きはR5RSプログラムとの互換性の
ために用意されています。
指定されたエラー範囲の中で、有限な実数xの正確な有理数表現のうち
最も簡単なものを返します。rationalize
やexact
はこの手続きを
下請けとして呼び出しています。通常はrationalize
(数値の演算参照)
を使い、real->rational
は誤差許容値をより細かく制御したい時のみ
使うのが良いでしょう。
返される有理数は次の条件を満たします。
(<= (- x lo) r (+ x hi)) ; when open? is #f (< (- x lo) r (+ x hi)) ; otherwise
hiとloは非負でなければなりません。
hiとloの両方、もしくは一方が省略された場合、それは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
(hiとlo引数を与えて open?を省略した場合は、 閉じた範囲と考えます。)
[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
数値への強制型変換手続きです。
objをそれぞれ数値もしくは正確な整数と解釈して返します。
数値と文字列に対してのメソッドは定義されています
(文字列はstring->number
を使って変換されます。
数値として解釈できない文字列に関しては0が返されます)。
その他のobjについては単に0が返されます。
x->integer
は、objが数値として表現できるけれど正確な整数では
ない場合、round
とinexact->exact
によって正確な整数に変換します。
他のクラスはこのメソッドを定義することにより、独自の変換関数を提供することができます。
これらの手続きは整数を半無限のビットベクタとして扱います。 正の整数の場合、数値の左側に無限に0が続いていると見倣されます。 負の整数の場合、数値は2の補数で表現され、左側に無限に1が続いていると見倣されます。
これらの操作の名前に関しては、Scheme界には大きく二つの流儀があります。
GaucheはSLIBの元々の“logical”モジュールに合わせました。
その起源はCommon Lispです。
もう一つの流儀では、arithmetic-shift
といった、より長く記述的な名前を使います。
R7RSビット演算ライブラリ(see scheme.bitwise
- R7RSビット演算)
は追加のビット演算を提供しています。
[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]
[SRFI-60]
整数n1 …の、それぞれビット論理積、
ビット論理和、ビット排他的論理積を返します。
ゼロ個の引数が与えられた場合は、logand
は-1
を、
logior
とlogxor
は0
を返します。
[SRFI-60] 整数nのビット否定を返します。
[SRFI-60]
≡ (not (zero? (logand n1 n2 …)))
[SRFI-60]
整数nのindex目のビットが1ならば#t
を、0ならば#f
を
返します。
nのビットのうち、set-bitsで1が立っているビットを立て、 clear-bitsで1が立っているビットをクリアした整数を返します。
実質的に(logand (logior n set-bits) (lognot clear-bits))
と同じです。
(logset+clear #b11000011 #b00001100 #b01000001) ⇒ 142 ;; #b10001110
[R7RS bitwise] 整数nのstartビット目(含む)からendビット目(含まない)までを 取り出した数値を返します。start < end でなければなりません。
[R7RS bitwise] bitが真の値なら、整数nのindexビット目をセットした数値を 返します。 bitが偽の値なら、整数nのindexビット目をリセットした数値を 返します。
[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))
[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
[R7RS bitwise] 正確な整数nを表現するのに必要な最小ビット数を返します。負の数は2 の補数で表現されるものと仮定しています。符号用のビットは考慮しません。
(integer-length 255) ⇒ 8 (integer-length 256) ⇒ 9 (integer-length -256) ⇒ 8 (integer-length -257) ⇒ 9
nが2の冪乗(expt 2 k)
(k >= 0
) ならその冪 k
を、
そうでなければ#f
を返します。
(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
- 整数に対するビット操作参照)。
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.bytevector
がbig
を使うので、
両方認識するようになっています。
little-endian
little
リトルエンディアン。32ビット整数値#x12345678
は#x78 #x56 #x34 #x12
のようなバイトシーケンスとして出力されます。
Gaucheはずっとlittle-endian
を使ってきましたが、
R7RS-largeに取り入れられたscheme.bytevector
がlittle
を使うので、
両方認識するようになっています。
arm-little-endian
これはlittle-endian
のバリエーションで、ARMプロセッサの
特定のモードで使われるものです。倍精度浮動小数点数以外はlittle-endian
と同様に動作します。倍精度浮動小数点数については、ふたつのリトルエンディアンワードが
ビッグエンディアンの順で書き出されます (例えばマシンレジスタ上でのビットパターンが
#x0102030405060708
の場合、出力は
#x04 #x03 #x02 #x01 #x08 #x07 #x06 #x05
となります)。
endian引数が省略された場合は、これらの手続きはパラメータdefault-endian
の
値を使います。
これは、バイナリ入出力ルーチンでendian指定が省略された場合に 共通して使われるエンディアンを指定する動的パラメータです (パラメータ参照)。 このパラメータの初期値はシステムのネイティブエンディアンです。
システムのネイティブエンディアンは次の手続きで得られます。
システムのエンディアンを示すシンボルを返します。