2012-05-02 21 views
2

long型の変数にデータを提供するAPIを使用しています。この変数の値は増加しており、複数回ロールオーバーしますが、残念ながらAPIを変更する方法はありません。私は、検出し、私は以下に含まましテストハーネスのようなコードを使用してオーバーフローを補正しようとしています最終的に私は長い符号なしlongにデータをキャストするつもりだし、その後、二重に:longでオーバーフローを処理する方法

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 

はこれまでのところですので、良い、値が我々は署名のための最大値を通過したにもかかわらず100000によって増加します32ビット長。

ダウンに..further ...

-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 

ので、私はこの間違ったを取得しています。ロールオーバーに適切に対処する方法についてのヒントはありますか? アドバイスをいただければ幸いです。ありがとう!

+1

あなたがしていることを解読するのはかなり難しいです。各ステップの意図を説明するコードにいくつかのコメントを追加すると役立ちます。しかし、あなたの問題は、上位ワードが1から2に切り替わる2回目のロールオーバを処理していないことが原因であるように見えます。 –

+1

ええ、あまりにも頑張っています。 'val - prevVal'を蓄積するだけです。これはあなたが2の補数系であることを前提としています。あなたは '__int64'を使っているようです。 –

+0

このリンクを確認してください:http://stackoverflow.com/questions/199333/best-way-to-detect-integer-overflow-in-c-c – Alexander

答えて

1

好奇心が強いですが、システムにはどれくらい長い時間がかかりますか?私は64ビットを推測していますが、あなたの質問は32ビットであることを暗示しています。また、なぜ二重にキャストすることを検討するのですか?ダブルスはあなたが思うほど大きくない。 52 to 53 bitsは私が扱ってきたシステムのほとんどからです。他のビットは指数に使用され、符号付きの場合は署名します(私は信じています)。あなたはC++を使用しているので、私はboost :: uint64_t integer.hppを使用して大きな数字を移植可能に格納します。

0

答えに感謝します。ロングは私のシステムでは32ビットですが、残念ながら私はかなりロックされたフレームワークで作業しているので、私はブーストを使用できません。

前述のように、私は複数のロールオーバーを処理していませんでした。 Raymondが言っているように、私はこれまでの私がテストして働いていたことを把握することでこれを処理することができました。もう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); 

ありがとう。

関連する問題