web-dev-qa-db-ja.com

2つの「float」を使用して「double」をエミュレートします

32ビットの単精度浮動小数点演算のみをサポートする組み込みハードウェア用のプログラムを書いています。ただし、私が実装しているアルゴリズムでは、64ビットの倍精度の加算と比較が必要です。 2つのdoublesのタプルを使用してfloatデータ型をエミュレートしようとしています。したがって、double dは、タプルを含むstructとしてエミュレートされます:(float d.hi, float d.low)

比較は、辞書式順序を使用して簡単である必要があります。ただし、どのベースを使用すればよいかわからないため、追加は少し注意が必要です。 FLT_MAX?そして、キャリーをどのように検出できますか?

これはどのように行うことができますか?


Edit(Clarity):追加の範囲ではなく、追加の有効数字が必要です。

58
user210870

倍精度浮動小数点は、単精度数値のペアを使用して、単精度指数範囲のわずかな減少を伴う単精度算術のほぼ2倍の精度を達成する手法です(範囲の遠端での中間のアンダーフローとオーバーフローのため)。 。基本的なアルゴリズムはT.Jによって開発されました。 1970年代のデッカーとウィリアムカハン。以下に、これらの手法をGPUにどのように適用できるかを示すかなり最近の2つのペーパーを示しますが、これらのペーパーで取り上げられている内容の多くは、プラットフォームに関係なく適用できるため、目前のタスクに役立つはずです。

https://hal.archives-ouvertes.fr/hal-0002144 Guillaume DaGraça、David Defourグラフィックハードウェアでのfloat-float演算子の実装、実数とコンピューターに関する第7回会議、RNC7。

http://andrewthall.org/papers/df64_qf128.pdf Andrew Thall GPU計算用の拡張精度浮動小数点数。

80
njuffa

これは簡単なことではありません。

浮動小数点数(IEEE 754単精度)には、1つの符号ビット、8つの指数ビット、および23ビットの仮数(まあ、実質的には24)があります。

倍精度(IEEE 754倍精度)には、1つの符号ビット、11の指数ビット、および52ビットの仮数(事実上53)があります。

フロートの1つから符号ビットと8つの指数ビットを使用できますが、他の3つの指数ビットと29ビットの仮数をどのように取得しますか?

たぶん他の誰かが賢いものを思いつくかもしれませんが、私の答えは「これは不可能です」です。 (または少なくとも、「64ビットの構造体を使用して独自の操作を実装するよりも簡単ではありません」)

10
Nemo

実行する操作の種類によって多少異なります。足し算と引き算だけに関心がある場合は、 Kahan Summation が優れた解決策になります。

6
Mr Fooz

精度と広い範囲の両方が必要な場合は、 SoftFloat などの倍精度浮動小数点のソフトウェア実装が必要になります。

(さらに、基本的な原則は、各値の表現(たとえば64ビット)を3つの構成部分(符号、指数、および仮数)に分割することです。次に、指数の差に基づいて1つの部分の仮数をシフトし、追加または符号ビットに基づいて他の部分の仮数から減算し、仮数をシフトし、それに応じて指数を調整することにより、結果を再正規化する可能性があります。その過程で、不必要な損失を避けるために、多くの面倒な詳細が説明されます。精度を高め、無限大、NaN、非正規化数などの特別な値を処理します。)

5

23桁を超える高精度のすべての制約を考えると、最も効果的な方法はカスタム算術パッケージを実装することだと思います。

簡単な調査では、BriggsのdoubledoubleC++ライブラリがあなたのニーズに対処し、その後いくつかのニーズに対処する必要があることを示しています。 this を参照してください。[*]デフォルトの実装はdoubleに基づいて30桁の有意な数値計算を実現しますが、floatを使用して13または14を実現するように簡単に書き換えられます。重要な数字。同様の大きさの値を持つ加算演算を分離し、最後の演算で極値を加算するだけの注意が払われている場合は、これで十分です。

ただし、コメントにはx87制御レジスタをいじくり回していると書かれています。詳細についてはチェックしませんでしたが、コードを移植できないために使用できない可能性があります。


[*] C++ソースはその記事によってリンクされていますが、gzip圧縮されたtarのみがデッドリンクではありませんでした。

3
wallyk

それは現実的ではありません。もしそうなら、埋め込まれたすべての32ビットプロセッサ(またはコンパイラ)は、倍精度をエミュレートすることになります。現状では、私が気付いていることは誰も行っていません。それらのほとんどは、単にfloatdoubleに置き換えます。

ダイナミックレンジではなく精度が必要な場合は、固定小数点を使用することをお勧めします。コンパイラが64ビットをサポートしている場合、これも簡単です。

3
phkahler

役に立つかもしれない別のソフトウェアベースのソリューション: GNU MPFR
それは他の多くの特別なケースを処理し、そうでなければ自分で処理しなければならないであろう任意の精度(64ビットdoubleより優れている)を許可します。

1
Ioan

これは、多くのコンパイラーが long double に対して使用する double-doublemath に似ています。ハードウェアdouble計算サポートのみを備えています。また、doubleサポートのない古いNVIDIA GPUでfloat-floatとして使用されます。 GPU上の2つのFP32でFP64をエミュレートする を参照してください。この方法では、計算はソフトウェアの浮動小数点ライブラリよりもはるかに高速になります。

ただし、ほとんどのマイクロコントローラーではfloatsのハードウェアサポートがないため、純粋にソフトウェアで実装されます。そのため、float-floatを使用するとnotパフォーマンスが向上し、指数の余分なバイトを節約するためにメモリオーバーヘッドが発生する可能性があります。

より長い仮数が本当に必要な場合は、カスタム浮動小数点ライブラリを使用してみてください。たとえば、40ビットの仮数と7ビットの指数だけが必要な場合は、ライブラリを変更して独自の新しい48ビットfloat型を適応させることができます。不要な16ビットの計算/保存に時間を費やす必要はもうありません。しかし、このライブラリは非常に効率的である必要があります。コンパイラのライブラリには、独自のタイプの浮動小数点に対するアセンブリレベルの最適化が含まれていることが多いためです。

0
phuclv