我正在编写一个将有符号整数空间映射到无符号整数空间的函数。但是我想在正数之前得到负数映射。
我想的方法是这样的 假设我们有一个带符号的64位整数a。
a
投射到128位a
然而,问题是,我正在使用的C实现没有128位整数。
有没有有效的方法呢?
答案 0 :(得分:6)
无符号类型的算术是模2 n (也就是说,它包裹着)。
所以你需要做的就是:
a
投射到无符号的64位a
答案 1 :(得分:2)
只需切换MSB位:
1.将a
转换为无符号的64位
2. xor 2 63 (或者你可以:加2 63 )。
这意味着您需要更改(xor)一位(位63) 样本输出:
a hex(a) map(a)
-9223372036854775808 0x8000000000000000 0x0000000000000000
-9223372036854775807 0x8000000000000001 0x0000000000000001
-9223372036854775806 0x8000000000000002 0x0000000000000002
-9223372036854775805 0x8000000000000003 0x0000000000000003
-1000 0xfffffffffffffc18 0x7ffffffffffffc18
-10 0xfffffffffffffff6 0x7ffffffffffffff6
-1 0xffffffffffffffff 0x7fffffffffffffff
0 0x0000000000000000 0x8000000000000000
1 0x0000000000000001 0x8000000000000001
10 0x000000000000000a 0x800000000000000a
100 0x0000000000000064 0x8000000000000064
1000 0x00000000000003e8 0x80000000000003e8
9223372036854775805 0x7ffffffffffffffd 0xfffffffffffffffd
9223372036854775806 0x7ffffffffffffffe 0xfffffffffffffffe
9223372036854775807 0x7fffffffffffffff 0xffffffffffffffff
示例代码(使用添加// xor
):
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
uint64_t show(int64_t n){
uint64_t u = (uint64_t)n;
u += (uint64_t)1 << 63; // u ^= (uint64_t)1 << 63;
printf("%21"PRId64" %21"PRIu64" 0x%016"PRIx64"\n", n, u, u);
return u;
}
int main()
{
show(-1000);
show(-10);
show(-1);
show(0);
show(1);
show(10);
show(100);
show(1000);
return 0;
}
使用union测试示例代码来演示位xor (只是小端):
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
typedef union {
uint8_t b[8];
int64_t i;
uint64_t u;
}T64bit;
uint64_t show(int64_t n){
T64bit t;
t.i = n;
t.b[7] ^= 0x80; // t.b[7] += 0x80;
printf("%21"PRId64" %21"PRIu64" 0x%016"PRIx64"\n", n, t.u, t.u);
return t.u;
}
int main()
{
show(-1000);
show(-10);
show(-1);
show(0);
show(1);
show(10);
show(100);
show(1000);
return 0;
}
输出:
-1000 9223372036854774808 0x7ffffffffffffc18
-10 9223372036854775798 0x7ffffffffffffff6
-1 9223372036854775807 0x7fffffffffffffff
0 9223372036854775808 0x8000000000000000
1 9223372036854775809 0x8000000000000001
10 9223372036854775818 0x800000000000000a
100 9223372036854775908 0x8000000000000064
1000 9223372036854776808 0x80000000000003e8