Language agnostic 如何在一个字节中反转ON位?
我在读乔尔的书,他在书中提出了一个采访问题: 编写一个程序来反转给定字节中的“开”位 我只能想到一个使用C的解决方案Language agnostic 如何在一个字节中反转ON位?,language-agnostic,Language Agnostic,我在读乔尔的书,他在书中提出了一个采访问题: 编写一个程序来反转给定字节中的“开”位 我只能想到一个使用C的解决方案 在这里提问,以便您可以向我展示如何以非C的方式进行操作(如果可能)该问题的具体含义是什么 相反是否意味着将1设置为0,反之亦然 或者它是指000011100-->00110000,在字节中反转它们的顺序?或者可能只是将前一个1的部分反转到最后一个1?即00110101-->00101011 假设这意味着颠倒整个字节的位顺序,下面是x86汇编程序版本: ; al is input
在这里提问,以便您可以向我展示如何以非C的方式进行操作(如果可能)该问题的具体含义是什么 相反是否意味着将1设置为0,反之亦然 或者它是指000011100-->00110000,在字节中反转它们的顺序?或者可能只是将前一个1的部分反转到最后一个1?即00110101-->00101011 假设这意味着颠倒整个字节的位顺序,下面是x86汇编程序版本:
; al is input register
; bl is output register
xor bl, bl ; clear output
; first bit
rcl al, 1 ; rotate al through carry
rcr bl, 1 ; rotate carry into bl
; duplicate above 2-line statements 7 more times for the other bits
不是最理想的解决方案,查表更快。颠倒C#中的位顺序:
字节反向字节(字节b)
{
字节r=0;
对于(int i=0;i i;
int reversedMask=bit经典页面有几种(非常聪明的)方法来实现这一点,但都是用C语言实现的。任何从C语法派生的语言(尤其是Java)都可能有类似的方法。我相信我们会在这个线程中得到一些Haskell版本;)
字节反向字节(字节b)
{
返回b^0xff;
}
如果在您的语言中,^
是XOR,那么这是可行的,但如果它是和
(通常是这样)就不行了
这个问题具体是什么意思
好问题。如果反转“开”位意味着只反转“开”位,则无论输入是什么,都将始终得到0。如果这意味着反转所有位,即将所有1更改为0,将所有0更改为1,这是我最初读取它的方式,那么这只是按位非或补码。基于C的语言有一个补码运算符,~
,可以实现此目的。例如:
unsigned char b = 102; /* 0x66, 01100110 */
unsigned char reverse = ~b; /* 0x99, 10011001 */
如果您正在谈论使用Ruby将1切换到0,将0切换到1:
n = 0b11001100
~n
如果你的意思是颠倒顺序:
n = 0b11001100
eval("0b" + n.to_s(2).reverse)
如果您的意思是计算位,如另一个用户所述:
n = 123
count = 0
0.upto(8) { |i| count = count + n[i] }
♥ Ruby我可能记错了,但我认为Joel的问题是计算“on”位,而不是反转它们。因为问题要求非C方式,下面是一个方案实现,愉快地抄袭了:
重写为C(对于不熟悉Scheme的人),它看起来是这样的(在Scheme中,数字可以任意大):
int
反向位(整数k,整数n)
{
int m=n<0?~n:n;
int-rvs=0;
而(-k>=0){
rvs=(rvs>=1;
}
返回n<0?~rvs:rvs;
}
int
反向位字段(整数n、整数开始、整数结束)
{
int width=结束-开始;
int mask=~-1>开始;
return(bit_reverse(width,zn)这里有一个直接剪切粘贴的版本,这很有趣,因为它不涉及循环。另一方面,与我发布的Scheme版本不同,这个版本只适用于32位和64位数字。:-)
32位版本:
public static int reverse(int i) {
// HD, Figure 7-1
i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;
i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;
i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;
i = (i << 24) | ((i & 0xff00) << 8) |
((i >>> 8) & 0xff00) | (i >>> 24);
return i;
}
public static long reverse(long i) {
// HD, Figure 7-1
i = (i & 0x5555555555555555L) << 1 | (i >>> 1) & 0x5555555555555555L;
i = (i & 0x3333333333333333L) << 2 | (i >>> 2) & 0x3333333333333333L;
i = (i & 0x0f0f0f0f0f0f0f0fL) << 4 | (i >>> 4) & 0x0f0f0f0f0f0f0f0fL;
i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL;
i = (i << 48) | ((i & 0xffff0000L) << 16) |
((i >>> 16) & 0xffff0000L) | (i >>> 48);
return i;
}
公共静态int反转(int i){
//HD,图7-1
i=(i&0x555555)>>1)和0x555555;
i=(i&0x33333333)>>2)和0x33333333;
i=(i&0x0f0f)>>4)和0x0f0f;
i=(i>8)&0xff00)|(i>>24);
返回i;
}
64位版本:
public static int reverse(int i) {
// HD, Figure 7-1
i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;
i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;
i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;
i = (i << 24) | ((i & 0xff00) << 8) |
((i >>> 8) & 0xff00) | (i >>> 24);
return i;
}
public static long reverse(long i) {
// HD, Figure 7-1
i = (i & 0x5555555555555555L) << 1 | (i >>> 1) & 0x5555555555555555L;
i = (i & 0x3333333333333333L) << 2 | (i >>> 2) & 0x3333333333333333L;
i = (i & 0x0f0f0f0f0f0f0f0fL) << 4 | (i >>> 4) & 0x0f0f0f0f0f0f0f0fL;
i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL;
i = (i << 48) | ((i & 0xffff0000L) << 16) |
((i >>> 16) & 0xffff0000L) | (i >>> 48);
return i;
}
公共静态长反转(长i){
//HD,图7-1
i=(i&0x555555L)>>1)和0x555555L;
i=(i&0x3333L)>>2)和0x3333L;
i=(i&0x0F0FL)>>4)和0x0F0FL;
i=(i&0x00ff00ff00ff00ff00ffl)>>8)和0x00ff00ff00ff00ffL;
i=(i>16)&0xffff0000L)|(i>>>48);
返回i;
}
我可能记错了,但我
我以为乔尔的问题是关于
计算“开”位而不是
逆转它们
给你:
#include <stdio.h>
int countBits(unsigned char byte);
int main(){
FILE* out = fopen( "bitcount.c" ,"w");
int i;
fprintf(out, "#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n\n");
fprintf(out, "int bitcount[256] = {");
for(i=0;i<256;i++){
fprintf(out, "%i", countBits((unsigned char)i));
if( i < 255 ) fprintf(out, ", ");
}
fprintf(out, "};\n\n");
fprintf(out, "int main(){\n");
fprintf(out, "srand ( time(NULL) );\n");
fprintf(out, "\tint num = rand() %% 256;\n");
fprintf(out, "\tprintf(\"The byte %%i has %%i bits set to ON.\\n\", num, bitcount[num]);\n");
fprintf(out, "\treturn 0;\n");
fprintf(out, "}\n");
fclose(out);
return 0;
}
int countBits(unsigned char byte){
unsigned char mask = 1;
int count = 0;
while(mask){
if( mask&byte ) count++;
mask <<= 1;
}
return count;
}
#包括
int countBits(无符号字符字节);
int main(){
FILE*out=fopen(“bitcount.c”、“w”);
int i;
fprintf(out,“#include\n#include\n#include\n\n”);
fprintf(out,“int位计数[256]={”);
对于(i=0;i,这里是用于补充位的强制性Haskell soln,它使用库函数complete:
import Data.Bits
import Data.Int
i = 123::Int
i32 = 123::Int32
i64 = 123::Int64
var2 = 123::Integer
test1 = sho i
test2 = sho i32
test3 = sho i64
test4 = sho var2 -- Exception
sho i = putStrLn $ showBits i ++ "\n" ++ (showBits $complement i)
showBits v = concatMap f (showBits2 v) where
f False = "0"
f True = "1"
showBits2 v = map (testBit v) [0..(bitSize v - 1)]
我将修改palmsey的第二个示例,消除一个bug并消除eval
:
n = 0b11001100
n.to_s(2).rjust(8, '0').reverse.to_i(2)
如果要按位反转的数字是一个固定长度的位字段,rjust
非常重要——如果没有它,0b00101010
的反转将是0b10101
,而不是正确的0b01010100
(显然,应该用所讨论的长度替换8)我刚刚被这个问题绊倒了。如果这个问题意味着翻转所有位,并且不允许使用类似C的运算符,例如XOR和NOT,那么这将起作用:
bFlipped = -1 - bInput;
我提出了一个技巧问题:)反转所有位意味着一个触发器,但只有打开的位清楚地表示:
return 0;
伪代码
while (Read())
Write(0);
在这里提问,以便您可以向我展示如何以非C方式进行操作(如果可能)
假设您的号码是10101010。要将1s更改为0s(反之亦然),只需使用XOR:
10101010
^11111111
--------
01010101
用手做这件事就像你会得到的“非C”
然而,从问题的措辞来看,它听起来似乎只是关闭了“开启”位……在这种情况下,答案是零(正如已经提到的)(当然,除非问题实际上是要求交换位的顺序)。反转位。
例如,我们有一个由011011表示的数字。现在如果我们反转位,那么这个数字将变成11010110。现在要实现这一点,您应该首先知道如何交换一个数字中的两个位。
交换数字中的两位:-
用一对两位进行异或运算,看结果是否不同。如果结果不一样,则两位相同,否则用异或运算对两位进行异或运算,并将其保存在原始数字中;
现在来倒数
对于小于Numberofbits/2的I
交换(Number,I,NumberOfBits-1-I);对所有1进行异或。
10101010
^11111111
--------
01010101