2

long 型の変数でデータを提供する API を使用しています。この変数の値は増加しており、何度もロールオーバーします。残念ながら、API を変更する方法はありません。以下に示すテスト ハーネスと同様のコードを使用して、オーバーフローを検出して補正しようとしています。最終的には、データを unsigned long long にキャストしてから double にキャストします。

void DetectRolloverOneNumber(long val)
{
static unsigned __int64 prevVal = 0;
//store value in an unsigned long
unsigned long newVal = val;

//we will eventually store in a long long
unsigned __int64 uiBigVal = newVal;

//max value for a 32 bit long
unsigned __int64 maxInt = 0xFFFFFFFF;
bool rollover = false;

//we will be adding max long + 1
maxInt++;

//detect the rollover
unsigned __int64 modVal = prevVal% maxInt;

if (newVal < modVal)
{
    //account for the rollover
    uiBigVal += maxInt;
    rollover = true;
}

cout<< val << "\t" << newVal << "\t" << modVal << "\t" <<
        uiBigVal << "\t" << prevVal << "\t" << rollover << "\n";

//cache the value so we can check for rollover next time
prevVal = uiBigVal;

したがって、これは問題なく機能しますが、長い値が複数回ロールオーバーしており、それを適切に処理していません。このコードをテストするには、次のように呼び出します

first =2147483647;
for (int i = 0; i < 100000; i ++)
{

    DetectRolloverOneNumber(first);
    first += 1000000;

ここに私の出力があります

   val (long)       newVal (ulong) modVal           uiBigVal       prevVal    
   2147483647      2147483647      0               2147483647      0       
   -2146483649     2148483647      2147483647      2148483647      2147483647
   -2145483649     2149483647      2148483647      2149483647      2148483647
   -2144483649     2150483647      2149483647      2150483647      2149483647
   -2143483649     2151483647      2150483647      2151483647      2150483647
   -2142483649     2152483647      2151483647      2152483647      2151483647

これまでのところ、符号付き 32 ビット長の最大値を渡したにもかかわらず、期待どおりに値が 100000 増加しています。

..さらに下に...

   -2483649        4292483647      4291483647      4292483647      4291483647
   -1483649        4293483647      4292483647      4293483647      4292483647
   -483649         4294483647      4293483647      4294483647      4293483647      
   516351          516351          4294483647      4295483647      4294483647   (rollover detected here and we are still good)
   1516351         1516351         516351          1516351         4295483647      
   2516351         2516351         1516351         2516351         1516351 //oops!!!
   3516351         3516351         2516351         3516351         2516351 

だから私はこれを間違えています。ロールオーバーを適切に処理する方法に関するヒントはありますか? アドバイスをいただければ幸いです。ありがとう!

4

2 に答える 2

1

ちょっと興味がありますが、あなたのシステムでは long の大きさはどのくらいですか? 私は64ビットを推測していますが、あなたの質問はそれらが32ビットであることを意味します. また、キャストを double にすることを検討する理由は何ですか? ダブルスはあなたが思っているほど大きくありません。52 ~ 53 ビットは、主に私が使用したシステムからのものです。他のビットは指数に使用され、符号付きタイプの場合は符号が使用されます(私は信じています)。C++ を使用しているので、boost::uint64_t integer.hppを使用して大きな数値を移植可能に格納します。

于 2012-05-02T01:41:41.963 に答える
0

答えてくれてありがとう。私のシステムでは long は 32 ビットですが、残念ながら私はかなりロックダウンされたフレームワークで作業しているため、boost を使用できません。

述べたように、私は複数のロールオーバーを処理していませんでした。レイモンドが述べたように、私がテストして動作する以前のものを追跡することでこれを処理できます。処理するもう 1 つの方法は、次のようなことを行って、私が見ているロールオーバーの数を追跡することです。

   //the rest of the code is the same as above
   if ((newVal < modVal && prevVal > 0))
  {
    //rollover has occurred, increment our rollover counter
    rolloverCount ++;
  }

  //account for the rollover
  uiBigVal =newVal + (maxInt * rolloverCount);

入力していただきありがとうございます。

于 2012-05-02T13:59:53.297 に答える