kubo39's blog

ただの雑記です。

D言語のftoa/dtoa実装

以前のポストで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を掛けていく。 これを表示上必要な桁に達するまで行う。 一番最後に表示される次の桁の数値をみて丸目モードを決定する。