0

まだ十分なテストを実行していませんが、何らかの理由で、特定の負でない値を使用すると、この関数は負の値を返すことがあります。電卓でさまざまな値を使用して多くの手動テストを行いましたが、これと同じ動作を表示することはまだありません。

私が何かを見逃していないかどうか、誰かが見てくれるかどうか疑問に思っていました。

float calcPop(int popRand1, int popRand2, int popRand3, float pERand, float pSRand)
{
    return ((((((23000 * popRand1) * popRand2) * pERand) * pSRand) * popRand3) / 8);
}

変数にはすべて、ランダムに生成された値が含まれています。

popRand1: 1 から 30 の間

popRand2: 10 から 30 の間

popRand3: 50 から 100 の間

pSRand: 1 から 1000 の間

pERand: 1.0f から 5500.0f の間で、上記の関数に渡される前に 0.001f で乗算されます

編集:

さて、実行をもう少し厳密に追跡した後、この関数の直接の障害ではありません。後でこのコードを使用すると、無限に正のフロートが生成され、負に反転します。

pPMax = (int)pPStore;

pPStore は、popCalc の戻り値を保持するフロートです。

問題は、数式がこれを行うのをどのように停止するかです。Calculator で非常に高い値を使用したテストでも、この動作が表示されたことはありません。コンパイラがこれを引き起こしている操作の順序を処理する方法に何かがありますか、それとも私の値が単に高すぎるだけですか?

4

3 に答える 3

1

この場合、関数が返された後に int に戻すと、int の最大値に達する可能性があるようです。より広い範囲の値を表すことができる型を使用することをお勧めします。

#include <iostream>
#include <limits>
#include <boost/multiprecision/cpp_int.hpp>

int main(int argc, char* argv[])
{
    std::cout << "int min: " << std::numeric_limits<int>::min() << std::endl;
    std::cout << "int max: " << std::numeric_limits<int>::max() << std::endl;
    std::cout << "long min: " << std::numeric_limits<long>::min() << std::endl;
    std::cout << "long max: " << std::numeric_limits<long>::max() << std::endl;
    std::cout << "long long min: " << std::numeric_limits<long long>::min() << std::endl;
    std::cout << "long long max: " << std::numeric_limits<long long>::max() << std::endl;

    boost::multiprecision::cpp_int bigint = 113850000000;
    int smallint = 113850000000;
    std::cout << bigint << std::endl;
    std::cout << smallint << std::endl;

    std::cin.get();
    return 0;
}

ここでわかるように、より大きな範囲を持つ他のタイプがあります。これらで十分でない場合は、最新のブースト バージョンが最適だと思います

于 2013-06-30T04:10:56.340 に答える
0

例外をスローします。

if (pPStore > static_cast<float>(INT_MAX)) {
    throw std::overflow_error("exceeds integer size");
} else {
   pPMax = static_cast<int>(pPStore);
}

または int の代わりに float を使用します。

于 2013-06-30T04:09:55.593 に答える
0

各項の最大値を掛け合わせると1.42312e+12、32 ビット整数が保持できる値よりも多少大きい値が得られます。そのため、浮動小数点から整数への変換について標準が何を述べているかを見てみましょう4.9/1

浮動小数点型の prvalue は、整数型の prvalue に変換できます。変換は切り捨てられます。つまり、小数部分は破棄されます。切り捨てられた値を変換先の型で表すことができない場合、動作は未定義です。

そのため、関数が生成できる可能性のある結果値の大規模なセグメントでは、32 ビット整数への変換が未定義になり、負の数になることがわかります。

ここにはいくつかのオプションがあります。に切り詰める代わりに、64 ビット整数型 (longまたはおそらく) を使用して値を保持できます。long longint

または、関数の結果を約 1000 分の 1 に縮小して、32 ビット整数が保持できる値の範囲内に最大の結果を維持することもできます。

于 2013-06-30T04:25:26.183 に答える