Astaroth
Astaroth

Reputation: 2291

Delphi: Can BinToHex() accepts a real binary number (base-2) in form of string in the first parameter?

Overview

Luckily, Delphi has an RTL function that converts a binary value into its hexadecimal representation, namely BinToHex(), declared in System.Classes as follows:

1.  procedure BinToHex(const Buffer: TBytes; BufOffset: Integer; var Text: TBytes; TextOffset: Integer; Count: Integer);
2.  procedure BinToHex(Buffer: PAnsiChar; Text: PAnsiChar; BufSize: Integer);
3.  procedure BinToHex(Buffer: PAnsiChar; Text: PWideChar; BufSize: Integer);
4.  procedure BinToHex(var Buffer; Text: PWideChar; BufSize: Integer);
5.  procedure BinToHex(var Buffer; Text: PAnsiChar; BufSize: Integer);
6.  procedure BinToHex(Buffer: Pointer; Text: PWideChar; BufSize: Integer);
7.  procedure BinToHex(Buffer: Pointer; Text: PAnsiChar; BufSize: Integer);

Delphi documentation states that the first parameter, i.e. Buffer is a pointer to an array of bytes. That means the function expects binary number passed as an array of bytes. Thus, one of possible way to convert binary to hexadecimal is as follows:

procedure Test();
var
  aBinNum : TBytes;
  sHexNum : string;
  iBinSize: Integer;

begin
  aBinNum := TBytes.Create(255, 7); // An array of decimal numbers, right?
  iBinSize := Length(aBinNum) * 2;
  SetLength(sHexNum, iBinSize);
  BinToHex(aBinNum, PWideChar(sHexNum), iBinSize);
  WriteLn(sHexNum); // The output is FF07
end;

The problem with this approach is that the binary number must be written as decimal number because there is no such 0b11111111 0b0111 as in GCC, for example.

Since the definition of binary number is a number expressed in the base-2 numeral system, I expect BinToHex() can receive a real base-2 number, maybe in form of string.

Question

Is it possible to use the 3rd form of BinToHex() so that I can pass a real base-2 number to the function?

If that is not possible, probably BinToHex() should be renamed to DecToHex() or BytesToHex(). Just kidding. :-)

Upvotes: 2

Views: 1365

Answers (1)

David Heffernan
David Heffernan

Reputation: 613302

BinToHex is not intended to convert from a binary representation of an integer, as you are expecting. What it does is simply encode an array of bytes as hex. For instance. If you pass BinToHex the following bytes:

1, 2, 255

then BinToHex will encode that as:

0102ff

By binary what is meant is simply an array of bytes. It is not meant to indicate an integer represented in base 2.

You are looking for a function like this:

function Base2TextToInt(const Text: string): Cardinal;
var
  Index: Integer;
  Digit: Cardinal;
begin
  Digit := 1;
  Result := 0;
  for Index := Length(Text) downto 1 do
  begin
    case Text[Index] of
    '0':
      ; // do nothing
    '1':
      inc(Result, Digit);
    else
      raise EConvertError.CreateFmt('''%s'' is not a valid binary digit.', [Text[Index]]);
    end;
    Digit := Digit shl 1;
  end;
end;

Note that I have ignored the error case of there being more than 32 digits. I'll leave that as an exercise to the reader.


One of the common misconceptions that people have is that a number can be a decimal number, or a binary number, and so on. Decimal, binary, etc. are just representations of a number. So, decimal 15 is equal to hex f is equal to binary 1111. These are all the same number, represented differently.

Now, on a computer, if you want to differentiate between representations of a number, you do so with text. When you write:

i := 15;
j := $f;

you have assigned the same value to i and j. You can write

Assert(i = j);

If you are looking to enter a binary representation of a number into your source code, you are out of luck. Delphi supports decimal and hexadecimal representations only.

If you wish to convert a number to its binary representation, or vice versa, you use a function like the one I gave above. That function converts from a binary representation, stored in a string, to a number.

Upvotes: 3

Related Questions