2

我正在使用一个 API,它在 long 类型的变量中提供一些数据。这个变量的值在增加,会多次翻转,遗憾的是没有办法修改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 位。另外,为什么要考虑加倍?双打并没有你想象的那么大。52 到 53 位,主要来自我使用过的系统。如果它是有符号类型(我相信),则其他位用于指数和符号。由于您使用的是 C++,我会使用 boost::uint64_t integer.hpp来便携地存储大数字。

于 2012-05-02T01:41:41.963 回答
0

感谢您的回答。Longs 在我的系统上是 32 位,不幸的是我不能使用 boost,因为我正在一个非常锁定的框架中工作。

如前所述,我没有处理多次翻转。正如雷蒙德所说,我可以通过跟踪我之前测试过并且确实有效的方式来处理这个问题。另一种处理方法是跟踪我看到的翻转次数,执行如下操作。

   //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 回答