0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SILVER HAIRED LISP (自作Lisp)数字型

0
Posted at

Javaで作っている自作Lispの数字型について考察しています。

浮動小数

common lispの浮動小数には、4つもの精度があります!

タイプ名 精度 文字列表記
SHORT-FLOAT 短精度 例: 1.23s0
SINGLE-FLOAT 単精度 例: 1.23f0
DOUBLE-FLOAT 倍精度 例: 1.23d0
LONG-FLOAT 高精度(処理系依存) 例: 1.23l0

分裂していたLisp方言を統一するため作成されたcommon lispの仕様ですが、
その頃はLispマシンというLisp専用のコンピュータが存在していて、
浮動小数の扱いがコンピュータ毎に違っていたそうです。
そのため、どの専用機であっても不公平にならないように4タイプもの精度が決められたそうです。
4つの精度を全て実装する必要はなく、1つだけでも良いそうです。
なおcommon lispの仕様が決まったのは、以下の年度です。

規格・名称 発行(承認)年
CLtL1 1984年
CLtL2 1990年
ANSI Common Lisp 1994年

IEEE 浮動小数点規格

「IEEE 浮動小数点規格」が決まった年を調べてみると、たしかにcommon lispの規格より後の年度になっています。

規格・名称 発行(承認)年
IEEE 754-1985 1985年
IEEE 854-1987 1987年

など

SBCLでは2タイプらしい

SBCLでは、2タイプにまとめられているそうです。
上2つが単精度、下2つが倍精度になっています。

タイプ名 精度 文字列表記
SHORT-FLOAT 単精度 例: 1.23s0
SINGLE-FLOAT 単精度 例: 1.23f0
DOUBLE-FLOAT 倍精度 例: 1.23d0
LONG-FLOAT 倍精度 例: 1.23l0

Javaの浮動小数事情

Javaは初期のバージョンから一貫して IEEE 754-1985に完全に準拠するよう設計されています。

本Lispでは、JavaのFloatとDoubleをそのまま使っている

結果的に、SBCLと同じです。

Lispタイプ名 精度 Lisp文字列表記
SHORT-FLOAT javaのFloat 例: 1.23s0
SINGLE-FLOAT javaのFloat 例: 1.23f0
DOUBLE-FLOAT javaのDouble 例: 1.23d0
LONG-FLOAT javaのDouble 例: 1.23l0

(タイプ名は、まだ実装していません。たぶん実装しないと思う)

固定小数

common lispでは、固定小数をfixnumとか、bignumと呼びます。
本Lispは、Java25で実装しており、LispからJava呼び出しを簡単に行える事も目指している為、Javaの数値型をそのまま使います。

データ型 最小値 最大値
int -2,147,483,648 2,147,483,647
long -9,223,372,036,854,775,808 9,223,372,036,854,775,807
BitInteger 不明 不明

Javaのintの動作

以下は、Javaのプログラムです。

    public static void main(String[] args) {

        int x = Integer.MAX_VALUE;
        System.out.println("x = " + x);
        x = x + 1;
        System.out.println("x + 1 = " + x);
    }

実行結果は以下になります。

x = 2147483647
x + 1 = -2147483648

intで扱える最大値を超えると、マイナスの値になります。
本Lispでも、Javaと同様の結果となります。

SHLISP
cl-user >> 2147483647

2147483647
java.lang.Integer
cl-user >> (+ 2147483647 1)

-2147483648
java.lang.Integer
cl-user >>

Javaのlongの動作

以下は、Javaのプログラムです。

    public static void main(String[] args) {

        long x = Long.MAX_VALUE;
        System.out.println("x = " + x);
        x = x + 1;
        System.out.println("x + 1 = " + x);
    }

実行結果は以下になります。

x = 9223372036854775807
x + 1 = -9223372036854775808

longで扱える最大値を超えると、マイナスの値になります。
本Lispでも、Javaと同様の結果となります。

SHLISP
cl-user >> 9223372036854775807

9223372036854775807
java.lang.Long
cl-user >> (+ 9223372036854775807 1)

-9223372036854775808
java.lang.Long

bignum(BigInteger)

本LispのREPLにlongの範囲外の数値を入れると、BigIntegerになります。

SHLISP
cl-user >> 9223372036854775808

9223372036854775808
java.math.BigInteger

Javaで、+ - * / が使えるのは、int, long, short, doubleのタイプです。
BigInteger型の足し算は addというメソッドを使う必要があります。
そのあたりも、本Lispでは、Javaの考え方に合わせています。

Common Lispにある、分数やbignumも、本Lispでは少しだけ実装しています。
しかしLispの + - * / では、分数やbignumは扱わない事にしました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?