位操作 Delphi 中的 XML - 按位运算

5

我是一名高中学生,目前正在学习Delphi XE3。我们正在学习BIT操作。我们有一个作业,虽然我已经阅读了很多关于这个主题的内容,并且理解了在位上存储信息和SHL/SHR的整个过程,但我仍然难以理解如何在Delphi中执行此过程。

作业如下:

Decimal        Hexidecimal    Binary
1              0x0001         0000000000000001
2              0x0002         0000000000000010
4              0x0004         0000000000000100

通过在XML文件中传递整数值来标识选项集。例如,如果我想发送选项1和选项2,我会添加1 + 2 = 3。 我将发送3作为数字来指定选项1和2为true。

在客户端,二进制值将为0000000000000011 = 3

根据我的阅读,我需要使用掩码,但我不知道如何做到这一点。我该如何在Delphi中使用掩码,以获取单个的真或假的值?

我尝试在常规整数变量中执行此操作,但它总是被视为整数,并且结果非常奇怪。 如果我将整数转换为二进制字符串表示形式,并遍历字符,则结果是正确的,但我认为我不应该使用字符串进行此操作。任何帮助或示例将不胜感激。谢谢。


请问您能否提出一个具体的问题?这里没有一个明确的问题。 - David Heffernan
我想了解如何从整数值中读取特定位是否设置以及如何设置特定位。如果值为1 + 4 = 5,则如何读取从右侧开始的第1位和第3位是否设置或等于True。 - LHearn
通常我们从0开始编号位。所以你要测试的是第0位和第2位。为了做到这一点,你需要写(x and 1)<>0来测试第0位,写(x and 4)<>0来测试第2位。你应该更直接地问这个问题。 - David Heffernan
X 是一个常规的整数或字节变量? - LHearn
@DavidHeffernan,谢谢。我应该如何使用SHL和SHR? - LHearn
对于位移操作,这里不需要使用它。例如,如果您想要从一个字节中提取出前4个比特位,您可以编写 b shr 4。或者从一个整数中获取高位字,i shr 16。或者将两个字合并成一个整数,(w1 shl 16) or w2 - David Heffernan
3个回答

3

通常使用二进制运算符and来检查一个整型变量中是否设置了特定的位,使用or运算符来设置单个位,例如:

const
  OPTION_X = $01;
  OPTION_Y = $02;
  OPTION_Z = $04;

var
  Options: Byte;
begin
  Options := OPTION_X or OPTION_Y;  //actually 3, like in your example
  //check if option_X is set
  if (Options and OPTION_X) = OPTION_X then
    ShowMessage('Option X is set');  //this message is shown, because the bit is set
  //check if option_Z is set
  if (Options and OPTION_Z) = OPTION_Z then
    ShowMessage('Option Z is set');  //this message is NOT shown
end;

不同的OPTION_常量实际上是掩码,即它们被用来将位屏蔽为0(检查特定位是否设置)或将位屏蔽为1(设置特定位)。考虑以下代码段:
begin
  ..

  if cbOptionX.Checked then
    Options := Options or OPTION_X;
  ..

or操作会将第一位掩码为1。如果我们从二进制的Options值01010000开始,结果的Options将是01010001。

    01010000   
 OR 00000001  //OPTION_X 
  = 01010001   

为了检查某个特定位是否设置,使用相同的值将所有其他位掩码为0。例如,条件语句:(Options and OPTION_Z) = OPTION_Z 就是这样做的:

  • first it MASKS all the non-interesting bytes of the Option variable to 0. If we consider the last value of 01010001, the operation will result in clearing all the bits, but the first.

        01010001   
    AND 00000001   
      = 00000001   
    
考虑起始值为01010000,它将返回零。
        01010000   
    AND 00000001   
      = 00000000   
  • 接下来,它比较该值是否等于掩码本身。如果相等,则原始的Options变量中设置了该位,否则未设置。如果您的掩码只包含一个位,那就是个人喜好,您可以检查结果值是否与0不同,但是如果您的掩码包含多个位并且您想检查是否所有位都已设置,则必须检查它们是否相等。

1
虽然所有回答都很有帮助,UWA Rabee 给出了最简单的答案,但我需要理解掩码的概念。@jachguate,非常感谢您。比我想象的要简单得多。 - LHearn
我读了测试单个位的代码。这也适用于我的评论。 - David Heffernan
@David 在我看来,相等性检查并不违反 DRY 原则。就像所说的那样,对于单个位(bit)而言它只是品味问题,并且与多个位掩码检查格式保持一致。 - jachguate
@David 当然,OPTION_X标识符出现了两次,但如果我想要检查按位与操作的结果是否等于OPTION_X,那么这如何违反DRY原则呢?我承认你喜欢检查<> 0,但在我看来,在这种情况下两者都同样有效。 - jachguate
1
@LHearn你的if语句看起来不错。为什么要遍历所有位值? - jachguate
显示剩余9条评论

2

Delphi有一个预定义类型TIntegerSet,允许使用集合运算符。假设options是一个整数,您可以像这样检查是否设置了任何位(从0开始):

option1 := 0 in TIntegerSet(options); { Bit 0 is set? }
option3 := 2 in TIntegerSet(options); { Bit 2 is set? }

更改选项是通过包含或排除实现的:
Include(TIntegerSet(options), 0); { set bit 0 }
Exclude(TIntegerSet(options), 2); { reset bit 2 }

当然,您可以使用任何其他有用的集合运算符。

1

Delphi有按位运算符,用于操作整数类型的各个位。查看shlshrandorxor运算符。要组合位,请使用or运算符。要测试位,请使用and运算符。例如,假设这些常量:

const
  Option1 = 0x0001;
  Option2 = 0x0002;
  Option3 = 0x0004;

“或”运算符会查看两个输入值的位,并生成一个输出值,在其中任一输入值具有“1”位的位置上,该输出值都将具有“1”位。因此,合并位看起来像这样:
var
  Value: Integer;
begin
  Value := Option1 or Option2;
  {
  00000000000000000000000000000001 Option1
  00000000000000000000000000000010 Option2
  -------------------------------- OR
  00000000000000000000000000000011 Result
  }
  ...
end;

and运算符查看两个输入值的位,并生成一个输出值,该输出值仅在两个输入值都具有1位的位置上具有1位,否则它将产生一个0位。因此,测试位将如下所示:

var
  Value: Integer;
  Option1Set: Boolean;
  Option2Set: Boolean;
  Option3Set: Boolean;
begin
  Value := 7; // Option1 or Option2 or Option3

  Option1Set := (Value and Option1) = Option1;
  {
  00000000000000000000000000000111 Value
  00000000000000000000000000000001 Option1
  -------------------------------- AND
  00000000000000000000000000000001 Result
  }

  Option2Set := (Value and Option2) = Option2;
  {
  00000000000000000000000000000111 Value
  00000000000000000000000000000010 Option2
  -------------------------------- AND
  00000000000000000000000000000010 Result
  }

  Option3Set := (Value and Option3) = Option3;
  {
  00000000000000000000000000000111 Value
  00000000000000000000000000000100 Option3
  -------------------------------- AND
  00000000000000000000000000000100 Result
  }
  ...
end;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接