我正在使用一个API,它在long类型的变量中提供一些数据。此变量的值正在增加并将翻转多次,遗憾的是无法修改API。我正在尝试使用类似于下面包含的测试工具的代码来检测并补偿溢出,最终我将数据转换为无符号长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
所以我弄错了。任何人都有关于如何妥善处理翻滚的任何提示? 任何意见,将不胜感激。谢谢!
答案 0 :(得分:1)
只是好奇,但你的系统有多长?我猜64位,但你的问题暗示它们是32位。另外,为什么考虑铸造加倍?双打没有你想象的那么大。 52 to 53 bits主要来自与我合作过的系统。其他位用于指数并签名,如果它是签名类型(我相信)。由于您使用的是C ++,我会使用boost :: uint64_t integer.hpp来存储大数字。
答案 1 :(得分: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);
感谢您的投入。