将多个int编码为double

时间:2012-05-25 06:18:50

标签: c++ encoding

我想用双精度编码一对整数。例如,说我想传递一个函数:

foo(int a, int b)

但我只需要一个双重来表示两个整数(即):

foo(double aAndB)

目前我通过在小数点的两边各有一个int(即10和15将变为10.15),然后将其转换为字符串流标记并提取这两个数字来实现。

然而,当涉及10和10这样的数字时,这有一个明显的缺陷,即它变为10.1。

有没有办法通过一些棘手的数学方法来做到这一点,以便我可以传递一个代表2个整数的双函数?

感谢。

6 个答案:

答案 0 :(得分:5)

由于(通常)double有64位,每个int有32位,你可以认为你可以直接将这些位存储到double中,例如:

int32_t i1 = rand();
int32_t i2 = rand();
int64_t x = (((int64_t)i1)<<32) | ((int64_t)i2);
double theDouble;
memcpy(&theDouble, &x, sizeof(theDouble));

......这样做“几乎有效”。也就是说,它适用于i1和i2的许多可能值 - 但不适用于所有这些值。特别是,对于IEEE754浮点格式,指数位设置为0x7ff的任何值都将被视为指示“NaN”,浮点硬件可以(并确实)将不同的NaN等效位模式转换回其首选位传递double作为参数时的NaN位模式等。

因此,在大多数情况下,将两个32位整数填充到一个double中似乎可以正常工作,但是如果你用所有可能的输入值测试它,你会发现一些情况,这些值在它们停留期间意外地发生了变化。当你再次解码它们时,它会变成不同的值。

当然,你可以通过小心设置double的尾数位来解决这个问题,但是每个整数只能给你26位,所以你只能存储+/- 33,554,432的整数值或者。也许这没关系,具体取决于你的用例。

我的建议是,找到一种不同的方式去做你想做的事情。在浮点变量中存储非浮点数据会产生麻烦,特别是如果您希望代码完全可移植的话。

答案 1 :(得分:4)

如果你很幸运并且int是半双,你可以存储这样的整数:

int a = 10;
int b = 20;
double d;

*(int *)&d = a;
*((int *)&d + 1) = b;

int outa = *((int *)&d);
int outb = *(((int *)&d) + 1);
printf("%d %d\n", outa, outb);

这通常不起作用/可移植性。如果double和int具有相同的位数,则无法实现。

答案 2 :(得分:3)

double可以精确表示最多53位的整数。如果你想保留一个26位和27位整数,这很容易:double combined = bits27*67108864.0 + bits26;

请注意,67108864是2 ^ 26。

答案 3 :(得分:1)

尝试定义这样的联合:

struct two_int {
    int a;
    int b;
};

union encoding {
    struct two_int a;
    double c;
};

但这样做可能会带来便携性方面的问题。请仔细检查这种适合您情况的方法。

答案 4 :(得分:1)

您可以使用二进制掩码并从“double”中提取信息。

例如:

double encode(int a, int b)
{
    double d = 0;
    d = d | a; 
    d = d | (b << 8);
    return d;
}

double decode(double d)
{
    a = d & 0xFF;
    b = (d >> 8) & 0xFF;
}

在编码部分,a将位于双变量d的低8位,b将位于d的高8位。

答案 5 :(得分:0)

如果你总是将两个整数传递给这个参数,那么传递一个双精度是没有意义的。而是将两个整数作为单独的整数传递,或者将它们包装在结构中。

你这样做的方式让你没有机会发现真正的双重和两个整数之间的差异。因此,我得出结论,通过执行上述描述,您将失去任何功能。