各状態が N 番目の入力桁または指数桁を処理する状態マシンに相当するものを (手動で) 構築したいようです。このステート マシンは、ツリーのような形になります (ループはありません!)。目標は、可能な限り整数演算を行い、(明らかに) 状態の状態変数 (「先頭のマイナス」、「位置 3 の小数点」) を暗黙的に記憶し、そのような値の割り当て、保存、および後でフェッチ/テストを回避することです。 . 入力文字のみに単純な古い「if」ステートメントを使用してステートマシンを実装します(したがって、ツリーはネストされたifのセットになります)。バッファ文字へのインライン アクセス。関数呼び出しで速度が低下することは望ましくありませんgetchar
。
先行ゼロは単純に非表示にすることができます。とてつもなく長い先頭のゼロ シーケンスを処理するには、ここでループが必要になる場合があります。最初のゼロ以外の数字は、アキュムレータをゼロにしたり、10 を掛けたりすることなく収集できます。最初の 4 ~ 9 桁のゼロ以外の数字 (16 ビットまたは 32 ビットの整数の場合) は、定数値 10 による整数乗算で収集できます (ほとんどのコンパイラでは、数回のシフトと加算に変換されます)。[上に: ゼロ以外の数字が見つかるまでゼロの数字は何の作業も必要とせず、N 個の連続するゼロに対して 10^N を乗算する必要があります。これらすべてをステートマシンに配線できます]。最初の 4 ~ 9 に続く数字は、マシンのワード サイズに応じて 32 ビットまたは 64 ビットの乗算を使用して収集できます。精度は気にしないので、32 ビットまたは 64 ビットの値を収集した後は、単純に数字を無視できます。私' アプリケーションがこれらの数字を実際に処理することに基づいて、ゼロ以外の数字の固定数がある場合、実際に停止できると思います。数字列に小数点があると、ステート マシン ツリーに分岐が発生します。そのブランチはポイントの暗黙的な位置を知っているため、後で適切に 10 のべき乗でスケーリングする方法を知っています。このコードのサイズが気に入らない場合は、努力すれば、いくつかのステート マシン サブツリーを組み合わせることができる場合があります。
[上に: 整数部分と小数部分を別々の (小さい) 整数として保持します。これには、整数部分と小数部分を組み合わせるために最後に追加の浮動小数点演算が必要になりますが、おそらく価値はありません]。
[上に: 数字のペアの 2 文字を 16 ビット値に収集し、16 ビット値を検索します。これにより、メモリアクセスと引き換えにレジスタでの乗算が回避されます。おそらく、最新のマシンではうまくいきません]。
「E」に遭遇すると、上記のように指数を整数として収集します。事前計算された乗数のテーブルで正確に事前計算された/スケーリングされた 10 の累乗を検索し ("-" 符号が指数に存在する場合は逆数)、収集された仮数を乗算します。(浮動小数点除算は絶対に行わないでください)。各指数収集ルーチンはツリーの異なるブランチ (リーフ) にあるため、10 の累乗のインデックスをオフセットすることによって、見かけ上または実際の小数点の位置を調整する必要があります。
[上に:ptr++
数値の文字がバッファーに線形に格納され、バッファーの境界を越えないことがわかっている場合、コストを回避できます。ツリー ブランチに沿った k 番目の状態では、k 番目の文字に としてアクセスできます*(start+k)
。優れたコンパイラは通常、アドレッシング モードでインデックス付きオフセットの "...+k" を隠すことができます。]
正しく実行すると、このスキームは、ゼロ以外の桁ごとに約 1 回の安価な乗加算、仮数の浮動小数点へのキャスト、および指数と小数点の位置によって結果をスケーリングするための浮動小数点乗算を 1 回実行します。
上記は実装していません。ループを使用してそのバージョンを実装しましたが、かなり高速です。