1

非常に大きな数で単純な算術演算を実行するプログラムを作成しました。boost multiprecision ライブラリの mpz_int と mpf_float を使用することに成功しましたが、目的を達成するにはさらに精度が必要であることがわかりました。mpfr ライブラリを使用して、精度の高い float を定義しようとしています。コードをコンパイルすることはできましたが、実行時エラー libc++abi.dylib: terminating with uncaught exception of type boost::exception_detail::clone_impl >: The string “1572…[4000 digits]…00.328” could有効な整数として解釈されません。

作成した mpfr_float を整数に変換しようとしているのが問題の原因であると感じています。整数である文字列から float を初期化し、切り捨てて整数に変換する前に何らかの除算を行います。これが私のtypedefです:

typedef boost::multiprecision::number<boost::multiprecision::mpfr_float_backend<4680> > bloatfloat;

私の宣言:

bloatfloat seed(“4716…etc.”);

そして私の試みた変換:

boost::multiprecision::mpz_int seedint = seed.convert_to<boost::multiprecision::mpz_int>();

この変換を実行して実行時エラーを回避するために誰かが私を助けてくれたら、とても感謝しています。私の混乱の原因はそれよりも深いところにあるのではないかと思うので、私のプロジェクトについて少し説明したいと思います。そして、私がしていることでもっと根本的に間違っていることがあるかどうか誰か教えていただけないでしょうか。

ランダムに見えるテキストのページを作成しようとしていますが、予測可能な疑似ランダム関数で構成されています。そのため、誰かが 1、次に 2、次に 3 を入力した場合、テキストの 3 ページ間にパターンがないことに気付くでしょうが、これらの数字のいずれかを入力すると、毎回同じテキストが返されます。29 文字のページのすべての可能性を 3200 回、つまり 29^3200 (約 10^4680) の可能性で作成しようとしています。

ホルトン シーケンスを使用して疑似ランダム品質を生成し、結果に 29^3200 を掛けています。

これが私のハルトンシーケンスです:

while (input>0) {
    denominator *=3;
    numerator = numerator * 3 + (input%3);
    input = input/3;
}

次に、結果の数値を基数 29 に基数変換して、1 ページのテキストを取得します。最初は mpz_int を 29^3200 (文字列から初期化) に使用しましたが、これは繰り返しパターンを生成することがわかりました。ホルトン シーケンスの分母が何であるかによって異なります。たとえば、分母 243 を生成する入力は、同じ 162 文字が 3200 文字から繰り返されるテキストのページを生成しますが、位置が異なります。

私のプログラムの基本変換セグメントは次のとおりです。

boost::multiprecision::mpz_int seedint(seed); //converts from mpf_float
boost::multiprecision::mpz_int holder = 0;
std::string permuda [29] = {" ", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", ",", "."};
std::string book = "";
holder = seedint%29;
int conversion = holder.convert_to<int>();
book = permuda[conversion];
while (seedint>=29) {
    seedint = seedint/29;
    holder = seedint%29;
    conversion = holder.convert_to<int>();
    book.insert(0,permuda[conversion]);
}
std::cout << book << "\n";

この繰り返しがなぜ起こったのかを理解するのに十分な数学の感覚はありませんが、直感でフロートに変更しました。これははるかに優れていることがわかりました。パターンははるかに短く、出力文字列の先頭 (より高い値を表す) にのみ表示され始めますが、最終的にはまだそこにあり、認識可能でした. mpf_float は mpf_float_1000 よりもうまく機能し、よりランダムに見える結果を生成するという点で、どちらも mpz_int よりもはるかに優れていることがわかりました。

前に述べたように、私の表面的な質問は単純です: この実行時エラーを回避するにはどうすればよいですか? しかし、私のより深い懸念は次のとおりです。a) なぜこれらのパターンが現れるのか? 精度の高い浮動小数点数がこれらの繰り返し文字列を排除するのは正しいですか? b) その場合、mpfr_float は最適なデータ型ですか? どの程度の精度を与えるべきですか?c) そうでない場合、どのデータ型を使用すればよいですか?

これらの質問に答えてくれる人にはとても感謝しています。

- -編集 - -

29^3280 をシードとして使用し、mpf_float に固執し、反復的な文字である最後の 80 文字を切り取るだけで、私が抱えていた問題を解決しました。ただし、固定精度と可変精度についてはまだ興味があります。より高いテンプレート パラメータを使用して固定精度 gmp_float を定義しようとすると、さらに悪い結果が得られました。固定精度と可変精度とは正確には何ですか?また、なぜそのような結果が得られるのでしょうか?

4

1 に答える 1