2

任意の大きなグリッドを処理する関数があります。を使用することにより、別の数の累乗のグリッドが double に収まるかどうかを計算する必要がありstd::powます。それができない場合は、別のブランチを取り、通常の代わりに gnu multiprecision ライブラリを使用したいと考えています。

次のことを簡単に確認する方法はありますか。

int a = 1024;
int b = 0-10;

if(checkPowFitsDouble(a, b)) {
    long c = static_cast<long>(std::pow(a, b)); //this will only work if b < 6
} else {
    mpz_t c; //yada yada gmp
}

私はcheckPowFitsDoubleに完全に困惑しています。私が知らない数学のトリックがあるかもしれません。

4

4 に答える 4

4

累乗がオーバーフローするかどうかを確認する一般的な方法は、対数を使用します。この考え方は、次の関係に基づいています。

a^b <= m <=> log(a^b) <= log(m) <=> b * log(a) <= log(m) <=> b <= log(m) / log(a)

例えば、

int a = 1024;

for (int b = 0; b < 10; ++b) {
    if (b * std::log(a) < std::log(std::numeric_limits<long>::max())) {
        long c = std::pow(a, b);
        std::cout << c << '\n';
    }
    else
        std::cout << "overflow\n";
}

これによりアイデアが得られます。これが役立つことを願っています。

于 2013-09-04T08:58:43.437 に答える
4

特にパフォーマンスが重要でない限り、試してみることをお勧めします。double をオーバーフローした場合は、std::powを返しHUGE_VALます。したがって、次のようなものです:

double val = std::pow(a, b);
if(val != HUGE_VAL) {
    ...
} else {
    mpz_t c; 
    //...
}
于 2013-09-04T08:47:24.370 に答える
2

底が 10 の対数を使用すると、数字std:pow(a, b)があると推測できます。log(a^b) = b log a次に、DBL_MAX までの値に適合する double に適合するかどうかを自明に確認できます。

ただし、この方法では、1 回計算するだけでなく、追加の計算が実行a^bされます。最初に GMP を使用してバージョンを測定し、オーバーフローをチェックすることで実際に測定可能で再現可能な利点が得られるかどうかを確認します。

EDIT:これを無視std::powしてください。オーバーフローが発生した場合に備えて、すでに適切な値を返しているので、それを使用してください。

于 2013-09-04T08:58:09.430 に答える