Schemeで扱える数値型には、正確数(exact number)と非正確数(inexact number)があります。
正確数とは誤差を含まない数のことです。
正確数どうしの計算は通常は正確数になります。
非正確数とは正確数でない数のことです。非正確数を含む計算をすると誤差が生じる可能性があります。
何が正確数であり何が非正確数かは次項で見ていきます。
正確数かどうか、または非正確数かどうかを調べる
正確数かどうかを調べるにはexact?手続きが使用できます。
非正確数かどうかを調べるにはinexact?手続きが使用できます。
例:
gosh> (exact? 100) ;; 整数は正確数である
#t
gosh> (exact? 1/3) ;; 分数(有理数)は正確数である
#t
gosh> (exact? 0.5) ;; 小数点数は非正確数である
#f
gosh> (exact? (* 100 1/3)) ;; 正確数どうしの演算は正確数である
#t
gosh> (exact? (/ 100 0.5)) ;; 非正確数を含む演算は非正確数である
#f
gosh> (inexact? 3) ;; 整数は非正確数ではない
#f
gosh> (inexact? 3.0) ;; 小数点数は非正確数である
#t
gosh> (inexact? 0.5+0.5i) ;; 複素数は非正確数である
#t
正確数どうしの計算の注意点
Gaucheでは正確な任意の実数と正確な任意の複素数はサポートされません。
したがって、正確数どおしの計算であっても結果が有理数の範囲に収まらない場合は不正確な実数や複素数になることがあります。
正確数が要求される手続き
Gaucheには正確数が要求される手続きがあります。
例えばベクタ要素の値を取り出すvector-ref手続きや、
文字列の要素の値を取り出すstring-refに渡すインデックスの値には正確な整数が要求されます。
vector-ref、string-refについては「データ構造」で説明します。
正確数と非正確数の相互変換
正確数から非正確数への変換はexact->inexact手続きを、非正確数から正確数への変換はinexct->exact手続きを使用します。
exact->inexact x ;; 正確数を非正確数に変換
inexact->exact x ;; 非正確数を正確数に変換
例:
gosh> (exact->inexact 100) ;; 正確数を非正確数に変換
100.0
gosh> (exact->inexact 1/3) ;; 正確数を非正確数に変換
0.3333333333333333
gosh> (inexact->exact 0.5) ;; 非正確数を正確数に変換
1/2
gosh> (inexact->exact 10.0) ;; 非正確数を正確数に変換
10
桁の丸め
Schemeで実数の桁を丸めるには以下の手続きが使用できます。
- round
- floor
- ceiling
- truncate
いくつか実例を見ていきましょう。
gosh> (round 0.5)
0.0
gosh> (round 1.1)
1.0
gosh> (round 0.9)
1.0
gosh> (round 0.6)
1.0
gosh> (floor 1.2)
1.0
gosh> (floor 0.9)
0.0
gosh> (ceiling 1.2)
2.0
gosh> (ceiling 0.9)
1.0
gosh> (truncate 1.2)
1.0
gosh> (truncate 0.9)
0.0
floorとceilingはそれぞれ引数を越えない最大の整数と、引数を下回らない最小の整数を返します。
truncateは引数の小数部をゼロの方向に向かって切捨てた整数を返します。
roundは引数に最も近い整数を返します。引数の小数部が0.5ぴったりだった場合はroundは最も近い偶数を返します。
gosh> (round 1/2)
0
gosh> (floor 1/2)
0
gosh> (ceiling 1/2)
1
gosh> (truncate 1/2)
0
引数が正確数なら結果も正確数が返ります。
Schemeで不正確数の桁を丸めて結果を正確数に変換するには、
丸めを適用した後にinexact->exactを適用します。
ただしこれらの操作は頻繁に行われるので、
Gaucheでは簡略化のため以下の手続きを用意しています。
- round->exact
- floor->exact
- ceiling->exact
- truncate->exact
gosh> (round->exact 0.5)
0
gosh> (floor->exact 0.5)
0
gosh> (ceiling->exact 0.5)
1
gosh> (truncate->exact 0.5)
0