怎么来用位操作实现64位数的加法和减法?

时间:2020-12-12 15:21:12
这里的64位数是值用64个bit来存储一个数字。我对位操作学的很不好,想了好久也没想出好的解决方法。

7 个解决方案

#1


怎么来用位操作实现64位数的加法和减法?
--------------------------------------
用位操作来实现二进制数的加减法?这个到是没听说过,二进制数的加减不是有它的运算规则吗?
加法运算          减法运算
 
1 + 0 = 1          1 - 0 = 1

1 + 1 =0 (进位1)   1 - 1 = 0

0 + 0 = 0          0 - 0 = 0

0 + 1 = 1          0 - 1 = 1 (借位1)


机器里面的加减已经是最简单的运算了。

#2


现在的CPU应该有专门实现64位整形运算的机器指令,
这里只给出一个用两个32位整形实现64位整形加减法例子,没有经过测试,可能有错误。

typedef struct { unsigned int high, low; } int64;

// a + b
int64 add(int64 a, int64 b)
{
  int64 result;
  unsigned int n;
  result.low = (a.low & 0x7fffffff) + (b.low & 0x7fffffff); // 防止溢出
  // 考虑进位
  n = (result.low & 0x80000000) + (a.low & 0x80000000) + (b.low & 0x80000000);
  result.low = (result.low & 0x7fffffff) | (n & 0x1)<<31;
  result.high = a.high + b.high + (n & 0x2);
  return result;
}

// a - b
// 对b取补码后,调用加法运算
int64 sub(int64 a, int64 b)
{
  int64 tmp;
  tmp.low = ~b.low;
  tmp.high = ~b.high;
  if (tmp.low != 0xffffffff)
    tmp.low += 1;
  else {
    tmp.low = 0;
    tmp.high += 1;
  }
  return add(a, tmp);
}

#3


从汇编角度来看,64位的加减法需要64位的寄存器,现在一般的机器是32位的(像eax,ebx等)
按2楼做法是可取的,就是要考虑一个进位问题

#4


SSE 128位寄存器 xmm0 - xmm7

#5


#include <stdio.h>
#include <stdlib.h>

#ifdef _MSC_VER
typedef __int64  lld;
#define lldfmt   "%I64d"
#define llddef( x )     x ## i64 
#else
typedef long long lld;
#define lldfmt   "%lld"
#define llddef( x )     x ## ll 
#endif

lld lld_add( lld a , lld b )
{
    lld c ;
    while( (c=a&b) != 0 )
        a ^= b  ,  b = c << 1 ;
    return a | b;
}

int main()
{
    lld  a = llddef( 221234567890 ) , b = llddef( 111234567890 );
    printf( lldfmt " + " lldfmt " == " lldfmt "\n" , a , b , lld_add( a , b ) );
return 0;
}


#6


减法..

lld lld_sub( lld a , lld b )
{
    return lld_add ( lld_add( a , ~b ) , 1 );
}

#7


to mLee79:

这样效率是不是也太慢了啊?为了做加减法,还需要使用一个循环?

#1


怎么来用位操作实现64位数的加法和减法?
--------------------------------------
用位操作来实现二进制数的加减法?这个到是没听说过,二进制数的加减不是有它的运算规则吗?
加法运算          减法运算
 
1 + 0 = 1          1 - 0 = 1

1 + 1 =0 (进位1)   1 - 1 = 0

0 + 0 = 0          0 - 0 = 0

0 + 1 = 1          0 - 1 = 1 (借位1)


机器里面的加减已经是最简单的运算了。

#2


现在的CPU应该有专门实现64位整形运算的机器指令,
这里只给出一个用两个32位整形实现64位整形加减法例子,没有经过测试,可能有错误。

typedef struct { unsigned int high, low; } int64;

// a + b
int64 add(int64 a, int64 b)
{
  int64 result;
  unsigned int n;
  result.low = (a.low & 0x7fffffff) + (b.low & 0x7fffffff); // 防止溢出
  // 考虑进位
  n = (result.low & 0x80000000) + (a.low & 0x80000000) + (b.low & 0x80000000);
  result.low = (result.low & 0x7fffffff) | (n & 0x1)<<31;
  result.high = a.high + b.high + (n & 0x2);
  return result;
}

// a - b
// 对b取补码后,调用加法运算
int64 sub(int64 a, int64 b)
{
  int64 tmp;
  tmp.low = ~b.low;
  tmp.high = ~b.high;
  if (tmp.low != 0xffffffff)
    tmp.low += 1;
  else {
    tmp.low = 0;
    tmp.high += 1;
  }
  return add(a, tmp);
}

#3


从汇编角度来看,64位的加减法需要64位的寄存器,现在一般的机器是32位的(像eax,ebx等)
按2楼做法是可取的,就是要考虑一个进位问题

#4


SSE 128位寄存器 xmm0 - xmm7

#5


#include <stdio.h>
#include <stdlib.h>

#ifdef _MSC_VER
typedef __int64  lld;
#define lldfmt   "%I64d"
#define llddef( x )     x ## i64 
#else
typedef long long lld;
#define lldfmt   "%lld"
#define llddef( x )     x ## ll 
#endif

lld lld_add( lld a , lld b )
{
    lld c ;
    while( (c=a&b) != 0 )
        a ^= b  ,  b = c << 1 ;
    return a | b;
}

int main()
{
    lld  a = llddef( 221234567890 ) , b = llddef( 111234567890 );
    printf( lldfmt " + " lldfmt " == " lldfmt "\n" , a , b , lld_add( a , b ) );
return 0;
}


#6


减法..

lld lld_sub( lld a , lld b )
{
    return lld_add ( lld_add( a , ~b ) , 1 );
}

#7


to mLee79:

这样效率是不是也太慢了啊?为了做加减法,还需要使用一个循环?