5

数学計算用の C ソース コードを生成する C++ で書かれたプログラムがあります。生成されたコードで定数が非常に多くのスペースを占めることに気付き、よりコンパクトな表現を探しています。

定数を生成するために、私は現在以下を使用しています:

double v = ...
cfile << std::scientific << std::setprecision(std::numeric_limits<double>::digits10 + 1) << v;

これはロスレス表現であると確信していますが、非常に肥大化しています。たとえば、0 と 1 は 0.000000000000000e+00 と 1.0000000000000000e+00 のように表されます。そして「0」。または「1.」同じくらい多くの情報を運びます。

定数をファイルに出力する方法はありますか? 人間の読者にとって見栄えがする必要はありません。プレーンな C コードで存在する場合はコンパイルするだけです (C99 の場合は、有効な C++ であることが望ましいです)。移植可能であれば、16 進数でも問題ありません。

編集:std::fixedコード スニペットで削除されました。

4

4 に答える 4

10

16 進浮動小数点 ( C の printf() の書式指定子 %a ) を使用できます。精度のすべてのビットを保持するように定義されています (C11、7.21.6.1p8、a,A指定子)。

cfile << std::hexfloat << v;

コンパイラ/標準ライブラリが をサポートしていないhexfloat場合は、C99 の%aprintf 指定子を使用できます (セクション 22.4.2.2.2 の C++11 テーブル 88 で指定されているように、これは同等です)。

printf("%a", v);

たとえば、次のプログラムは有効な C99 です。

#include <stdio.h>
int main() {
   double v = 0x1.8p+1;
   printf("%a\n", v);
}

生成されたソース ファイルは有効な C++11 ではありません。C++11 は 16 進浮動小数点リテラルをサポートしていません。ただし、多くの C++11 コンパイラは、拡張機能として C99 16 進浮動小数点リテラルをサポートしています。

于 2013-03-01T11:41:22.273 に答える
3

これは、表現、言語、または標準ライブラリの問題ではなく、アルゴリズムの問​​題です。コード ジェネレーターがある場合は、生成されたコードを最適な (= 必要な精度で最短の) 表現に変更してみませんか? これは、コードを手で書くときに行うことです。

仮想put_constant(double value)ルーチンでは、書き込む必要がある値を確認できます

  • 整数ですか?std::fixedandでコードを肥大化させないでくださいset_precision。整数にキャストしてドットを追加してください。
  • デフォルト設定で文字列に変換してからdouble、に戻してみてください。何も変更されていない場合は、デフォルト (短い) 表現で十分です。
  • 実際の実装で文字列に変換し、その長さを確認してください。それが N より大きい場合 (後述) は別の表現を使用し、それ以外の場合はそれを記述します。

桁数が多い場合の浮動小数点数の可能な (短い) 表現は、メモリ表現を使用することです。これにより、かなり固定されたオーバーヘッドがあり、長さが変わることはないため、非常に長い数値にのみ適用する必要があります。それがどのように機能するかを示す単純な例:

#define USE_L2D __int64 ___tmp = 0;
#define L2D(x) (double&)(___tmp=x)

int main(int argc, char* argv[])
{
    // 2.2 = in memory it is 0x400199999999999A

    USE_L2D
    double f1 = L2D(0x400199999999999A);
    double f2 = 123456.1234567891234567;

    return 0;
}
于 2013-03-01T11:18:44.250 に答える
1

std::scientificまず、最初に、、次にと言うとき、あなたは自分自身と矛盾しています std::fixed。そして第二に、あなたはおそらくどちらも欲しくないでしょう。デフォルトの形式は、通常、これを最適に行うように設計されています。デフォルトの形式には名前もマニピュレーターもありませんが、他の形式が指定されていない場合に取得されるものであり、次を使用して設定できます(他のコードが別の形式を設定した場合)。

cfile.setf( std::ios_base::fmtflags(), std::ios_base::floatfield );

これを使用することをお勧めします。(もちろん、精度はまだ必要です。)

于 2013-03-01T11:24:00.480 に答える
-4

このように浮動小数点を無損失で渡すことができるかどうかはわかりません。浮動小数点は必然的に損失があります。値のサブセットを正確に表すことはできますが、すべての有効数字を含めることはできません。ハードウェアが異なれば表現も異なる可能性があるため、情報の損失がないことを保証することはできません。受信側のハードウェアで値を表現できない可能性があるため、すべてを渡すことができたとしても。

ただし、単純な ofstream::operator<< は必要な数の数字を出力するため、問題を複雑にする必要は実際にはありません。

于 2013-03-01T11:18:08.863 に答える