简体   繁体   English

如何将2 ^ 63添加到带符号的64位整数并将其转换为无符号的64位整数,而不使用中间的128位整数

[英]How to add 2^63 to a signed 64-bit integer and cast it to a unsigned 64-bit integer without using 128-bit integer in the middle

I am writing a function that map signed integer space to unsigned integer space. 我正在编写一个将有符号整数空间映射到无符号整数空间的函数。 But I want the negative number map before the positive number. 但是我想要正数之前的负数映射。

The method I am thinking of work like this let say we have a signed 64-bit integer a. 我想这样工作的方法就是说我们有一个带符号的64位整数a。

  1. Cast a to 128-bit a为128位
  2. Add 2 63 to a 添加2 63a
  3. Cast it to unsigned 64-bit 将其转换为无符号64位

However, the problem is, the C implementation I am working with does not have 128-bit integers. 但问题是,我正在使用的C实现没有128位整数。

Is there any efficient way of doing this? 有没有有效的方法呢?

Arithmetic in unsigned types is modulo 2 n (that is, it wraps around). 无符号类型中的算术是模2 n (即,它包裹)。

So all you need to do is: 所以你需要做的就是:

  1. Cast a to unsigned 64-bit a为无符号64位
  2. Add 2 63 to a 添加2 63a

just toggle MSB bit : 只需切换MSB位
1. cast a to unsigned 64-bit 1.将a为无符号64位
2. xor with 2 63 (or you may: add 2 63 ). 2. xor with 2 63 (或者你可以:加2 63 )。

which means you need to change (xor) just one bit (bit 63) sample output: 这意味着您需要更改(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  

sample code (using add // xor ): 示例代码(使用add // 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;
}

test sample code using union to demonstrate bit xor (just little-endian): 使用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;
}

output: 输出:

        -1000   9223372036854774808 0x7ffffffffffffc18
          -10   9223372036854775798 0x7ffffffffffffff6
           -1   9223372036854775807 0x7fffffffffffffff
            0   9223372036854775808 0x8000000000000000
            1   9223372036854775809 0x8000000000000001
           10   9223372036854775818 0x800000000000000a
          100   9223372036854775908 0x8000000000000064
         1000   9223372036854776808 0x80000000000003e8

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM