2

I am working with an API that provides some data in a variable of type long. The value of this variable is increasing and will rollover multiple times, unfortunately there is no way to modify the API. I'm attempting to detect and compensate for the overflow using code similar to the test harness I've included below, ultimately I'm going to cast the data to an unsigned long long and then to a 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;

So this works ok but my long value is rolling over multiple times and I am not handling that properly. To test this code I call it with the following

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

    DetectRolloverOneNumber(first);
    first += 1000000;

Here is my output

   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

so far so good, values increasing by 100000 as expected even though we passed the max value for a signed 32 bit long.

..further on down...

   -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 

so I'm getting this wrong. Anybody have any tips on how to properly deal with the rollover? Any advice would be appreciated. Thanks!

mash
  • 467
  • 7
  • 14
  • 1
    It's pretty hard to decipher what you're doing. Adding some comments to the code that explains the intent of each step would help. But your problem appears to be that you're not handling the second rollover, where the high-order word switches from 1 to 2. – Hot Licks May 02 '12 at 01:36
  • 1
    Um, you're trying too hard. Just accumulate `val - prevVal`. This assumes you are on a 2's complement system, which it seems that you are given that you're using `__int64`. – Raymond Chen May 02 '12 at 01:46
  • Check this link: http://stackoverflow.com/questions/199333/best-way-to-detect-integer-overflow-in-c-c – Aligus May 02 '12 at 14:51

2 Answers2

1

Just curious, but how big is a long on your system? I'm guessing 64 bits, but your question implies they are 32 bits. Also, why consider casting to double? doubles aren't as big as you may think. 52 to 53 bits mostly from the systems I've worked with. The other bits are used for the exponent and sign if it's a signed type (I believe). Since you are using C++, I would use boost::uint64_t integer.hpp to portably store big numbers.

0

thanks for the answers. Longs are 32 bits on my system, unfortunately I can't use boost because I'm working in a pretty locked down framework.

As stated I wasn't handling multiple rollovers. As Raymond stated I could handle this by keeping track of my previous which I've tested and does work. The other way to handle is to just keep track of the number of rollovers I am seeing, doing something like the following.

   //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);

Thanks for the input.

mash
  • 467
  • 7
  • 14