Fortran中如何交换整数指定二进制位 实现0与2位、1与3位互换
问题说明
现有整数2,4位二进制表示为0010(位编号从最低位开始以0为起始计数),需要交换两组指定位:位置0与位置2的位、位置1与位置3的位,目标输出为二进制1000对应十进制数值8。
使用mvbits编写的如下代码运行后得到结果为10,不符合预期:
integer :: s1 s1= 2 call mvbits(s1,1,1,s1,3)
原因解释
Fortran内置的mvbits是位覆盖拷贝子程序,不具备位交换功能:
- 子程序逻辑为从源变量的指定起始位开始,拷贝指定位长度的内容,覆盖写入目标变量的对应位置,不会保留目标位置原有值,也不会修改源位置的原有值
- 语法规范明确要求,当源变量和目标变量为同一个变量时,源位区间和目标位区间不能重叠,否则运行结果为未定义值
上述代码仅将s1位1上的1拷贝覆盖到了位3,位1上原有的1没有被清除,最终二进制为1010即十进制10,和预期结果不符。
实现方案
Fortran没有提供可直接完成指定位交换的内置函数,可通过临时变量暂存位值的方式,配合mvbits实现无覆盖的位交换:
integer :: s1, tmp s1 = 2 ! 初始二进制0010 ! 暂存两组待交换的位段 tmp = 0 call mvbits(s1, 0, 2, tmp, 0) ! 暂存低2位(位0、位1) call mvbits(s1, 2, 2, tmp, 2) ! 暂存高2位(位2、位3) ! 交叉写入完成交换 s1 = 0 call mvbits(tmp, 0, 2, s1, 2) ! 原低2位写入高2位位置 call mvbits(tmp, 2, 2, s1, 0) ! 原高2位写入低2位位置 ! 运行后s1值为8,对应二进制1000,符合预期
如果是不连续的零散位交换,可搭配btest、ibset、ibclr三个内置位操作函数,逐位读取两个待交换位置的位值,清空两个位置后再将读取的值交叉写入对应位置即可。
内容的提问来源于stack exchange,提问作者geom
相关产品推荐
相关产品推荐

