我有int A, B, C
。并且A
在范围内0-9999
,B
是0-99
,C
是0-99
。
因为函数必须只返回一个double
,所以我想把它们都放在一个数字中。否则我需要调用函数三次。但我无法编写有效的代码来做到这一点。这将被调用数百万次,因此它应该非常有效,但没有 ASM。
我需要一个函数double pack3int_to_double(int A, int B, int C) {}
我有int A, B, C
。并且A
在范围内0-9999
,B
是0-99
,C
是0-99
。
因为函数必须只返回一个double
,所以我想把它们都放在一个数字中。否则我需要调用函数三次。但我无法编写有效的代码来做到这一点。这将被调用数百万次,因此它应该非常有效,但没有 ASM。
我需要一个函数double pack3int_to_double(int A, int B, int C) {}
你不能只存储 A + 1000B + 100000C 吗?
例如,如果您想存储 A = 1234、B = 6 和 C = 89,则只需存储
89061234
CCBAAAA
然后,您可以通过将 double 转换为 anint
并使用标准整数除法和模数技巧来恢复各个值来提取数字。
希望这可以帮助!
如果 A<10,000 且 B & C <100,则 A 可以用 14 位表示,B & C 可以用 8 位表示。因此,您总共需要 30 位。
因此,您可以通过将整数移动到正确的位置来打包/解包整数:
int packed = A + B<<14 + C<<22;
A = packed & 0x3FFF; B = (packed >> 14) & 0xFF; C = (packed >> 22) & 0xFF;
位移当然比乘法/除法快得多,您可以将 int 转换为 double ,反之亦然。
从技术上讲,这不是合法的 C 代码,因此您将自担风险使用它:
typedef union {
double x;
struct {
unsigned a : 14;
unsigned b : 7;
unsigned c : 7;
} y;
} result_t;
C 标准不允许使用联合成员写入值并使用不同的成员将其读出,但我不知道有编译器会进行静态分析来诊断此类问题(这并不意味着赢了以后不要这样做)。此外,使用某些int
值可能会导致double
. 但是,如果您知道您的系统不会生成任何陷阱表示,您可以考虑使用它。
double pack3int_to_double(int A, int B, int C) {
result_t r;
r.y.a = A;
r.y.b = B;
r.y.c = C;
return r.x;
}
void unpack3int_from_double (double X, int *A, int *B, int *C) {
result_t r = { X };
*A = r.y.a;
*B = r.y.b;
*C = r.y.c;
}
受您的回答的启发,这就是我到目前为止的想法。这应该是相当高效的,并且只使用了 32 位exponent
,所以double
不会触及 的 。
struct pack_abc {
unsigned short a;
unsigned char b, c;
int safety;
};
double pack3int_to_double(int A, int B, int C) {
struct pack_abc R = {A, B, C, 0}; // or 0 could be replaced with something smater, like NaN?
return *(double*)&R;
}
void main() {
int w = 1234, a = 56, d = 78;
int W, A, D, i;
double p = pack3int_to_double(w, a, d);
// we got the data packed into 'p', now let's unpack it
struct pack_abc *R = (struct pack_abc*) & p;
printf("%i %i %i\n", (int)R->a, (int)R->b, (int)R->c);
}
您可以在函数调用中使用 out 参数并检索所有 3 个 int 变量。
您可以使用存储在尾数中的数据返回 NaN 双精度值。这为您提供了 53 位可供使用。应该很多。