正如大卫在这里回答的评论中所问的,我对这个函数的工作原理非常感兴趣,因为如果将结果长度从32改为16或8,我似乎无法得到相同(正确)的值。
我用函数
function IntToBin(Value: LongWord): string;
var
i: Integer;
begin
SetLength(Result, 32);
for i := 1 to 32 do begin
if ((Value shl (i-1)) shr 31) = 0 then begin
Result[i] := '0'
end else begin
Result[i] := '1';
end;
end;
end;
这在某种程度上工作得很好。(1返回为000....001,2返回为000....010,3返回为000...011,等等...)。
然而,由于我只需要8个字符长的字符串结果,我将函数中的数字改为8,得到以下结果:
function IntToBin(Value: LongWord): string;
var
i: Integer;
begin
SetLength(Result, 8);
for i := 1 to 8 do begin
if ((Value shl (i-1)) shr 7) = 0 then begin
Result[i] := '0'
end else begin
Result[i] := '1';
end;
end;
end;
但我得到的结果如下:
1: 00000001
2: 00000011
3: 00000011
4: 00000111
5: 00000111
6: 00000111
7: 00000111
8: 00001111
9: 00001111
10: 00001111
11: 00001111
12: 00001111
16岁的人也是这样,而不是8岁。
尝试将长字更改为整数和字节,但得到相同的结果。
所以......嗯......我在这里错过了什么,不明白吗?:/
PS:出于学习的目的,在第一个函数的末尾用Copy(Result,25,8)解决了我的情况,因为需要传递8个字符长的字符串,但我真的很想弄明白是怎么回事...:)
谢谢
6条答案
按热度按时间pqwbnv8z1#
作为David so clearly answered,您的位移位太短,或者编译器隐式扩展了操作数。
如果性能很重要,那么下面的例程比大卫介绍的例程更快:
通过使用指针,可以避免在每次更新字符串时对其进行保护。这里不需要保护,因为程序的其他部分无法访问
Result
字符串。Delphi 中的字符串保护机制被称为"Copy On Write" (COW),它通过一个引用计数器来计数每个引用该字符串的示例。当一个字符串被写入并且引用计数大于1时,一个新的字符串被分配用于写入。
mkshixfv2#
代码中的左移意味着将你感兴趣的位移到数据类型的最左手。这样做,左边的所有位都会移离末端并丢失。然后当你再次右移时,我们会一直移到另一端。结果是0或1。
然而,你的数据类型仍然是32位,所以你的移位还不够远,你没有让目标位左边的所有位都从末尾掉下来,所以当你向右移位时,它们又会回来。
要使代码正常工作,您需要:
相对于原始版本,一个可能更容易理解的版本如下:
不过,坦白地说,最好是对一个字节进行操作。我发现这种双移位有点晦涩。我会使用一个单移位和一个位掩码。就像这样:
然后这样称呼它
假设
Value
是一个32位的数据类型,显然如果它已经是Byte
,那么你就不需要按位的and
。而原来的32位函数会读起来更好,像这样,在我的拙见。
此答案的早期版本在解决问题时有以下错误尝试:
问题是,即使
Value
是一个8位类型,按位操作也是在32位寄存器中执行的。因此,当执行右移时,左移到位数〉7的位返回。你可以通过屏蔽掉那些应该从末尾掉下来的位来很容易地解决这个问题。如下所示:这段代码非常复杂,我不建议任何人使用它。在我看来,最好的版本是我答案中的第三段代码。
0h4hbjxa3#
就我个人而言,我会这么做:
a8jjtwal4#
gmol16395#
vuv7lop36#
我不得不为我的南非IT 12级期末考试2020考试写这个。它是在一个GUI应用程序中,对于这个例子,我使用了一个控制台应用程序。