以前のポストでftoa実装がナイーブな感じであるという話はしたが、説明はしてなかったので残しておく。
アルゴリズム
D言語の浮動小数点数の10進表記アルゴリズムは指数部の数値によって3種類のアルゴリズムを使い分けている。
- Algorithm A: 指数部が大きい場合 (exp >= T.mant_dig)
- (例: doubleの場合) exp >= 53 のとき
- Algorithm B: 指数部が小さい場合 (exp < T.mant_dig - 61)
- (例: doubleの場合) exp < -8 のとき
- Algorithm C: 指数部が0に近い場合
- 上記の中間の数値
ここの指数部の値はIEEE754におけるバイアスなどを引いた後の値であることに注意する。
Algorithm A
表示される数値: 仮数部のあとに0がいくつも続くような見た目になる。
この場合は少数部がないので、単純に整数部分を10で割っていく。 整数部分をulongだけで表現できない場合のためにBigIntと同じようにulongの配列を使う。 その際は割り算の計算の単純化と高速化のためにulongのうち60bitのみを使う。
割り算は整数の割り算を使い、計算結果の上位4ビットがキャリーとして使われる。
Algorithm B
表示される数値: 0とドットのあとに複数の0が続き、そのあと仮数部が表示される。
この場合は整数パートが存在しない。 このアルゴリズムでは10をどんどん掛けていって、整数部分を取り除く。 このアルゴリズムでも数値はulongの配列として保持し、ulongのうち60bitしか使用しない。
乗算では普通の整数乗算を利用し、その結果最上位4ビットに桁が入ることがある。 この4ビットはキャリーとして次の乗算結果に加算される。
Algorithm C
この場合は整数パートと少数部が存在し、それぞれ1個のulongで表現できる。 そのためこれが一番高速になる。
仮数部は両方のパートか少数部に出現する。
最初に整数部を10で割っていく。次に少数部に10を掛けていく。 これを表示上必要な桁に達するまで行う。 一番最後に表示される次の桁の数値をみて丸目モードを決定する。