¥chapter{数値}

コンピューティングプロセッサ (CPU) は、コンピュータシステムの中心部であり、様々な形式の整数や浮動点小数の演算をサポートしています。プログラミング言語は、これらを, 例えばC言語の場合、char}, short}, int}, long} long long int}, float}, double}, long double}のように、異なる型で区別して利用できるようになっています。一方、Konoha は、プロセッサの性能やメモリ効率を最大利用するより、プログラミングのしやすさに力点を置いています。そのため、最も使いやすい整数と浮動小数点の形式を選んで、Int} と Float}クラスとして箱詰め(boxing)しています。本章では、これらのクラスを用いた数値の扱いを説明していきます。

% Integers are the most basic data type. Konoha differs from programming languages such as C and Java in that it does not make a distinction between short integers and long integers. All integers in Konoha are represented as values of the Int class. Konoha represents integers using the 64-bit integer number, which means it can represent integers ranging - to + (inclusive).

% Floating-point numbers are another basic datatype. All floating-point numbers in Konoha are represented as values of the Float class. Unlike the name implies, Konoha represents floats using the 64-bit floating-point format defined by the IEEE 745 standard, called double in C, C++, and Java.

== 数値と型}

Konohaは、２種類の数値表現をサポートしています。これらは、C言語における64ビット符号付き整数(long long int) と倍精度浮動小数点数(double)に相当し、日常的な利用においては自然数や実数を表現するのに十分な値域と精度を持っています。

Konohaでは、``Everything is an Object''の設計であり、数値を含め、すべての値はオブジェクトとなっています。Int}クラスとFloat}クラスは、それぞれ整数値と浮動小数点数値を箱詰め(boxing)してインスタンス化するためのクラスです。
 
{{{
>>> (1).class
Int
}}}

注意：「箱詰め(boxing)」の話だけをすると、プログラミング言語実装に詳しい方は不安になるだろう。Konohaの内部をより正確にいえば、オブジェクトとしてアクセスするときのみ、boxingされており、それ以外は、もちろん unboxing された状態で数値処理されています。不必要なメモリ消費は最低限に抑えられています。

=== int}, float}型}

Konoha では、クラス名は英大文字で始まり、そのまま型名として用いられます。このルールにしたがえば、整数値、浮動少数点値を用いるための型は、Int}, Float}型となります。しかし、C/C++, Java など、ほとんどすべてのプログラミング言語において、これらの型はint}, float}のように英小文字で始まっています。

ここで、言語設計の統一的美しさにこだわれば、Konohaのルールにしたがってもらえばよいものであるが、「言語」というものは実際に使っている人たちが主人公です。プログラミング言語も、そろそろ半世紀の歴史をもつわけであるから、言語設計者が好き勝手に文法を決められる時代はもう終わったと考えてよいだろう。統一的な美しさはないが、Konohaでは、int} や float}も別名定義し、プログラム中で利用することができます。

最後に、Konoha風のInt}と伝統的なint}のどちらを使った方がよいかという問題が残る。Konohaのローカルルールに固執してInt}/Float}を使うより、C/C++やJavaなどとソースコードの交換性を保つため、int}/float}を使う方がよいと考える。また、同じ理由で long}やdouble}型も定義されており、Int}/Float}の別名として定義されています。

=== Decimal**}

将来、小数点以下の精度を保持した無限長の数値をサポートすることを計画しています。


== 数値演算}

Konohaでは、数値はクラスによって箱詰めされているが、その値はそのままネイティブの数値表現、C言語で言うところの long long int と doubleです。したがって、その数値演算の振る舞いは、C言語の演算子と同じです。特に、浮動小数点演算において計算結果が微妙に異なることがバグレポートとして報告されるが、そもそも浮動小数点演算というのは桁落ち、丸め誤差などが含まれていることを思い出して欲しい。

=== 四則演算}

Int}, Float}は、それぞれの型の範囲において四則演算(+,-,*./)を定義しています。つまり、Int}型間の演算ではInt}型の結果がえられ、Float}型間の演算では、結果はFloat}型になります。

{{{
>>> 7 / 2                  // Int型の除算
3
>>> 7.0 / 2.0              // Float型の除算
3.5000000
}}}

一方、Int}型とFloat}型を混在して演算したときは、Int}型の値は全て自動的にFloat}型に変換されたのち、演算されます。したがって、結果はFloat}型となります。

{{{
>>> 7 / 2.0               // 7は7.0へ
3.5000000
>>> 7.0 / 2               // 2は、2.0へ
3.5000000
}}}

ゼロ除算の場合は、Int}, Float}ともに、Arithmetic!!|例外が通知されます。

{{{
>>> 1 / 0                 // ゼロ除算
Arithmetic!!: Zero Divide
}}}

¥subsubsection{優先順位}

Konoha の四則演算は、日常の数学の演算と同じ順序で計算されます。つまり、乗算と除算は、加算と減算に優先して実行されます。演算の優先順位を変更するときは、優先対したい演算を()で囲む。

{{{
>>> 1 + 2 * 3
7
>>> (1 + 2) * 3
9
}}}

Konohaでは、四則演算以外にも数多くの演算子をサポートしています。これらを混在して利用するときは、優先する演算子を()で囲む習慣をつけると、思わぬ誤動作を防ぎ、また読みやすさも向上する。

=== ビット演算}

Konohaは、Int}型の数値のみ、ビット演算をサポートしています。

{{{
>>> %bits(1)
00000000 00000000 00000000 00000001
>>> %bits(‾1)
11111111 11111111 11111111 11111110
>>> %bits(2)
00000000 00000000 00000000 00000010
>>> %bits(1&2)
00000000 00000000 00000000 00000000
>>> %bits(1|2)
00000000 00000000 00000000 00000011
>>> %bits(1<<4)
00000000 00000000 00000000 00010000
>>> 
}}}

スクリプティング言語では、低レベルな処理を書く機会が少ないため、ビット演算子を活用する機会は少ない。さらに、Konoha では、ビット演算子の記法は他のよく使われるオペレータ(¥verb#|a|#yやOUT << "hi"|など)に転用されているため、演算子の優先度がC/C++, Java と異なることがあります。この違いを覚えるよりは、ビット演算子と四則演算子を組み合わせるときは、()|で囲んで優先する演算子を明示した方がよい。

{{{
>>> %bits(1+1<<2)                    // 優先度が？
00000000 00000000 00000000 00001000
>>> %bits(1+(1<<2))
00000000 00000000 00000000 00000101
>>> %bits((1+1)<<2)
00000000 00000000 00000000 00001000
}}}

¥index{Float@Float.floatToIntBits}  ¥index{Float@Float.intBitsToFloat}
Floatの数値をIEEE 754 浮動小数点のビットレイアウトにしたがってビット演算をしたいときは、
まずFloat.floatToIntBits()|を用いてInt}型へ変換したのち、Float.intBitsToFloat()|でFloat}型に変換することで可能になります。ちなみに、Konohaは32ビットシステムであっても、Int}とFloat}はともに64ビットで表現されます。

{{{
>>> n = (float)1.0;                 // 数値変換
>>> %bits(n)
00000000 00000000 00000000 00000001
>>> f = Float.floatToIntBits(1.0)   // ビットレイアウト維持
>>> %bits(f)
00111111 11110000 00000000 00000000
}}}

=== 比較演算}

Int}型, Float}型は、ともに比較演算子(==|, !=|, <|, <=|, >=|, >|)によって数値を比較できます。また、Int}型、Float}型の比較を混在して用いたとき、Konohaは通常、異なる型の比較はオブジェクトIDによる比較になるが、特別に自動的にIntクラスをFloatクラスに変換して比較を行う。

{{{
>>> 1 < 2.0
true
>>> 3.2 != 3
false
}}}

Int}型の比較演算子は、実用上問題がおこらないが、Float}型の場合は、IEEE754規格に基づいた表現のため、実用上は同値であっても同値とみなされない。そこで、(正規表現のための)マッチング演算子=‾|を用いると、簡単にほぼ等しいを演算することができます。有効桁数は、小数点以下5桁です。

{{{
>>> 1.00003 == 1.0
false
>>> 1.00003 =‾ 1.0
true
}}}

=== 数値変換}

Konohaでは、Int型とFloat型の型変換は、必要に応じて自動的に行われます。これらを明示的におこないたい場合は、キャスト演算を用いることができます。ただし、Konohaの数値変換の振る舞いは、C言語の数値変換の振る舞いに基づいています。特に、Float}からInt}への変換は、切り捨てになるため注意が必要です。

{{{
>>> (int)1.8
1
>>> (int)-1.8
-1
}}}

¥index{Math@Math.ceil} ¥index{Math@Math.round}, ¥index{Math@Math.floor}
小数点以下 n 桁で切り上げ、四捨五入、切り下げを行いときは、math}パッケージのクラス関数Math.ceil()|, Math.round()|, Math.floor()|を用います。

{{{
>>> using math.*;
>>> Math.ceil(1.8)
2.0000000
>>> Math.round(1.8)
2.0000000
>>> Math.floor(1.8)
1.0000000
}}}

=== 文字列との変換}

Konohaは、全てのクラス間の変換がキャスト演算子に統合されています。文字列への変換も文字列からの変換もキャストで行うことができます。ただし、数値の書式を指定したい場合は、次節のフォーマッタを用います。

{{{
>>> (String)1.8
"1.8000000"
>>> (int)"123"
123
}}}

文字列から数値への変換は、数値リテラルの文法も解釈されます。

{{{
>>> (int)"1"
1
>>> (int)"0xff"
255
>>> (float)"6.0221415e23"
602214149999999896780800.000000
}}}

数値以外の文字列は、それぞれInt}型、Float}型のデフォルト値へ変換されます。デフォルト値の代わりに（変換に失敗したことを知るために）null}を得たいときは、Nullable キャストを用いることができます。

{{{
>>> (int)"hello,world"         // 数値でない
0
>>> (int?)"hello,world"        // 数値でない
null
}}}

== 数値フォーマッタ}

数値フォーマッタは、C言語printf|書式に由来しているものが多いが、独自に定義されたものは%bits|などいくつか存在する。ここでは、代表的な数値フォーマッタについて紹介する。

=== 10進書式 ¥%d}

10進数(digit)書式では、文字列の幅$m$ を$%|m{¥tt d}$のように指定できます。
また、$%|0m{¥tt d}$ように書式を与えると、空白の代わりに0で埋められます。（これは、数値としての順序が文字列化したときも保持されるため、よく用いられます。）

{{{
>>> %d(123)                    
"123"
>>> %4d(123)                    // 幅(4)を指定
" 123"
>>> %-4d(123)                   // 左寄せ
"123 "
>>> %04d(123)                   // 0パディング
"0123"
}}}

=== 16進書式 ¥%x}

10進数(digit)書式では、10進書式同様に、文字列の幅$m$ を$%|m{¥tt x}$のように指定できます。

{{{
>>> %x(123)                    
"7b"
>>> %8x(123)                   // 文字列の幅 8
"      7b"
>>> %08x(123)                  // 0パディング
"0000007b"
}}}

=== 小数書式 ¥%f}

小数書式は、Float}クラスだけでなく、Int}クラスもサポートしています。したがって、整数も型変換することないしに、小数書式でフォーマッティング可能です。

{{{
>>> %f(1)
1.000000
>>> %f(1.0)
1.000000
}}}

小数書式では、全体の幅$m$ と小数点以下の桁数$n$を$%|m.n{¥tt f}$のように指定できます。

{{{
>>> %f(3.14159)
"3.141590"
>>> %6.2f(3.14159)             // 小数点以下2桁
"  3.14"
>>> %6.3f(3.14159)             // 小数点以下3桁
" 3.142"
}}}

=== ビット書式 ¥%bits}

ビット書式は、printf}書式に存在しない独自の書式です。整数や浮動小数点数のビットレイアウトを確認するために導入されており、クラスルーム用途の書式です。

{{{
>>> %bits(-1)                    // 2の補数表現 :)
11111111 11111111 11111111 11111111
}}}

=== UCS4文字書式 ¥%c}

文字書式は、printf}書式でもおなじみの書式であり、整数から文字コードを用いて文字に変換してくれる。ただし、Konoha 言語では、Unicode文字コード(UCS4)を用いているため、ASCII 文字コード以外の文字も変換することができます。

{{{
>>> %c(30)                       // ASCII (<128)
"A"
>>> %c(0x3042)                   // UCS4  (>128)
"あ"
}}}

== 乱数生成}

¥index{Int.random} ¥index{Float.random}

乱数生成は、Int}とFloat}クラスの値をランダムに生成する一種のコンストラクタです。Konoha では、標準乱数生成器として、統計処理分野で愛用される高品質な疑似乱数アルゴリズム Mersenne Twister ¥cite{mt} を採用しています。

乱数生成は、クラス関数として提供されています。Int.random(n)|は、0からn|(含まれない)までの整数乱数を生成し、Float Float.random()|は、浮動小数点乱数x ($0.0 < x < 1.0$)を生成するクラス関数です。

例えば、さいころ(1〜6)を作りたいときは、次のように用いることができます。

{{{
>>> Int.random(6) + 1           // さいころ
3
>>> Int.random(6) + 1           // 違う目が出た
6
}}}
n
=== 乱数生成器の初期化}
¥index{System.setRandomSeed}

Konohaは、起動時の時刻とラインタイム情報から起動する度に乱数生成器を初期化しています。そのため、通常、乱数生成器を初期化する必要はない。ただし、明示的に乱数生成器を初期化したいときは、System.setRandomSeed(seed)|を用いることで、再初期化可能です。(パラメータseed|に対し、0を与えたときのみ、その時刻とランタイム情報からシードが生成されます。)

{{{
>>> System.setRandomSeed(1)　  // 初期化 
>>> Int.random()               // 初期化後は同じ　 
1234794094773155764
}}}

注意：同じ seed 値で初期化すると、乱数生成系列が同じになります。つまり、毎回、同じ順番で同じ乱数生成が繰り返されます。ただし、Konoha の乱数生成器は、複数の言語エンジン/スレッドから共有されているため、マルチ言語インスタンスやスレッド実行下での乱数生成は、逆に同一性は保証されなくなります。

