关于用位运算交换两个数的值

时间:2022-07-11 23:23:09
谭浩强<C程序设计>一书第300页中有这样一个知识点:
交换两个数的值,不用临时变量.
a=a^b;/*^是异或操作*/
b=b^a;
a=a^b;
这样a,b的值就互换了.
例如:
       a= 1011   (a=11)
      ^b= 0101   (b=5)
       a= 1110    a的值变为14
      ^b= 0101    
       b= 1011    b的值变为11
      ^a= 1110
       a= 0101    ab的值变为5
所以a,b的值就互换了.
但我在使用过程中发现了问题,不知何解,特向高人请教.

下面的程序是用选择法进行排序.
我用位运算法时出现错误.不知是何原因.

main()
{ int aa[10]={1222,5455,6423,6516,3105,3544,3344,4345,1024,6554};
  int i,j,k;
  int temp;
  for(i=0;i<9;i++)
  {  k=i;
     for(j=i+1;j<10;j++)
if(aa[k]<aa[j]) k=j;
/*     temp=aa[k];
     aa[k]=aa[i];
     aa[i]=temp;
 */
     aa[k]^=aa[i];
     aa[i]^=aa[k];
     aa[k]^=aa[i];

  }
  for(i=0;i<10;i++)
  {  printf("aa[%d]=%d\n",i,aa[i]);
  }
}
运算结果是:aa[0]=6554
           aa[1]=6516
           aa[2]=0
           aa[3]=0
           aa[4]=4345
           aa[5]=0
           aa[6]=0
           aa[7]=0
           aa[8]=1222
           aa[9]=1024
但如果用程序中注释的部分,则运算结果正确.
谢谢指教!!!

2 个解决方案

#1


你用的不是选择法吧,应该叫交换法,自己感觉是这样叫的。程序不是位运算的问题,
if(aa[k]<aa[j]) k=j; /*问题在这里,你的程序是不管k和i的值相不相等你都在交换,所以用*/
/*     temp=aa[k];   /*temp来交换当然没问题了,可是当你用aa[k]^=aa[i];aa[i]^=aa[k];

                     /*aa[k]^=aa[i];来交换的时候却不同了,当k与i相等的时候,异或的结
                     /*果总为0的,所以就不对了,*/

     aa[k]=aa[i];
     aa[i]=temp;
 */   
      aa[k]^=aa[i];
      aa[i]^=aa[k];
      aa[k]^=aa[i];

帮你改了下,程序如下:
#include<stdio.h>
#include<conio.h>
main()
{
int aa[10]={1222,5455,6423,6516,3105,3544,3344,4345,1024,6554};
int i,j,k;
int temp;
clrscr();
for(i=0;i<9;i++)
{  k=i;
for(j=i+1;j<10;j++)
if(aa[k]<aa[j]) k=j;
if( i != k ) /*{
temp=aa[k];
aa[k]=aa[i];
aa[i]=temp;
}              */

{aa[k]^=aa[i];
aa[i]^=aa[k];
aa[k]^=aa[i];
}

}
for(i=0;i<10;i++)
{  printf("aa[%d]=%d\n",i,aa[i]);
}
getchar();
}


#2


楼上正解,关于交换两个数,有很多有趣的方法,比如还可以:
int a, b;
a=a+b;
b=a-b;
a=a-b;
这样也可以交换。

#1


你用的不是选择法吧,应该叫交换法,自己感觉是这样叫的。程序不是位运算的问题,
if(aa[k]<aa[j]) k=j; /*问题在这里,你的程序是不管k和i的值相不相等你都在交换,所以用*/
/*     temp=aa[k];   /*temp来交换当然没问题了,可是当你用aa[k]^=aa[i];aa[i]^=aa[k];

                     /*aa[k]^=aa[i];来交换的时候却不同了,当k与i相等的时候,异或的结
                     /*果总为0的,所以就不对了,*/

     aa[k]=aa[i];
     aa[i]=temp;
 */   
      aa[k]^=aa[i];
      aa[i]^=aa[k];
      aa[k]^=aa[i];

帮你改了下,程序如下:
#include<stdio.h>
#include<conio.h>
main()
{
int aa[10]={1222,5455,6423,6516,3105,3544,3344,4345,1024,6554};
int i,j,k;
int temp;
clrscr();
for(i=0;i<9;i++)
{  k=i;
for(j=i+1;j<10;j++)
if(aa[k]<aa[j]) k=j;
if( i != k ) /*{
temp=aa[k];
aa[k]=aa[i];
aa[i]=temp;
}              */

{aa[k]^=aa[i];
aa[i]^=aa[k];
aa[k]^=aa[i];
}

}
for(i=0;i<10;i++)
{  printf("aa[%d]=%d\n",i,aa[i]);
}
getchar();
}


#2


楼上正解,关于交换两个数,有很多有趣的方法,比如还可以:
int a, b;
a=a+b;
b=a-b;
a=a-b;
这样也可以交换。