正如大卫在答案评论中所问的那样here ,我对这个函数的工作原理非常感兴趣,因为如果将结果长度从 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 个有点相同。
也尝试将 LongWord 更改为 Integer 和 Byte,但得到了相同的结果。
所以...嗯...我在这里错过了什么,并且不明白? :/
PS:出于学习目的询问,在第一个函数末尾用 Copy(Result, 25, 8) 解决了我的情况,因为需要传递 8 个字符长的字符串,但我真的想了解发生了什么...... :)
谢谢
最佳答案
如David so clearly answered ,您的位移位太短,或者操作数已被编译器隐式扩展。
如果性能很重要,这里有一个比 David 介绍的更快的例程:
function IntToBinByte(Value: Byte): String;
var
i: Integer;
pStr: PChar;
begin
SetLength(Result, 8);
pStr := PChar(Pointer(Result)); // Get a pointer to the string
for i := 7 downto 0 do begin
pStr[i] := Char(Ord('0') + ((Value shr (7 - i)) and 1));
end;
end;
通过使用指针,您可以避免在每次更新字符串时都对其进行保护。这里不需要保护,因为程序的任何其他部分都无法访问 Result
字符串。
Delphi中的字符串保护方案称为"Copy On Write" (COW) ,并通过一个引用计数器来工作,该计数器对引用该字符串的每个实例进行计数。当写入一个字符串并且引用计数大于1时,会分配一个新的字符串进行写入。
关于delphi - 将十进制/整数转换为二进制 - 它如何以及为什么这样工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21361627/