## Recommended Posts

I imagine one of the biggest problems of being self-taught is missing out on some well-documented practices.  Well, I confess that I did not know about the use of double-dabble to quickly manually convert a base-2 representation to base-10, for example: 1001000110 to 582.  Quick blog post published today:

• 2

Hm, I always convert to hex as an intermediary step (and actually prefer hex constants in source code). and I can still do binary to hex and back in my head, back from the C64 times.

• 1

1 hour ago, dummzeuch said:

I can still do binary to hex and back in my head

You mean to say that you've memorized all the 16 hex digits? Wow  I have mountain of things that need to be done right now, but what to say !, i am bored to hell and looking something to do away from what is needed, so.

@Darian Miller this is special for you

```program BinaryNumbers;

{\$APPTYPE CONSOLE}

{\$R *.res}

uses
System.SysUtils;

function IntToBin(Value: Integer; Digits: Integer = 0): string;
var
I, Len: Integer;
Negative: Boolean;
begin
// Set boundaries and limits
Negative := Value < 0;
if Negative then
Value := 0 - Value;
Len := 1;
while (1 shl Len) <= Value do
Len := Len + 1;
if Digits < 1 then
Digits := 1
else if Digits > 31 then
Digits := 31;
if Len < Digits then
Len := Digits;
Len := Len + Ord(Negative);

// Do translate
SetLength(Result, Len);
I := 0;
while Value > 0 do
begin
Result[Len - I] := Char((Value and 1) + Ord('0'));
Value := Value shr 1;
Inc(I);
end;

while I < Digits do
begin
Result[Len - I] := '0';
Inc(I);
end;
if Negative then
Result := '-';
end;

function DoubleToBin(Value: Double; Digits: Integer = 0; FracDigits: Integer = 8): string;
var
I, Len: Integer;
IntPart: Integer;
FractalPart: Double;
begin
IntPart := Trunc(Value);
Result := IntToBin(IntPart, Digits);

// Prepare result for fractal part
FractalPart := Value - IntPart;
if FractalPart < 0 then
FractalPart := 0 - FractalPart;
if (FracDigits > 0) or (FractalPart > 0) then
Result := Result + '.';

// Set boundaries and limits for fractal part
Len := 0;
if FracDigits < 0 then
FracDigits := 0;
if Len < FracDigits then
Len := FracDigits;
if Len = 0 then
Exit;

// Do translate
I := Length(Result);
SetLength(Result, I + Len);
Inc(FracDigits, I);
while (FractalPart > 0) and (I < FracDigits) do
begin
FractalPart := FractalPart * 2;
Inc(I);
Result[I] := Char(Ord(FractalPart >= 1) + Ord('0'));
if FractalPart >= 1 then
FractalPart := FractalPart - 1;
end;

// Fill trailing zeroes, up to FracDigits
while (I < FracDigits) do
begin
Inc(I);
Result[I] := '0';
end;
end;

function BinaryToInt(const Value: string): Integer;

procedure NotValidOfIntegerException;
begin
raise Exception.Create('BinaryToInt Error : ''' + Value + ''' is not valid binary integer');
end;

var
I, S, Len: Integer;
Negative: Boolean;
begin
//  Check validity and set boundaries
Result := 0;
Len := Length(Value);
if Len = 0 then
Exit;
Negative := Value = '-';
if Negative then
begin
if Len = 1 then
NotValidOfIntegerException;
S := 2;
end
else
S := 1;
for I := S to Len do
if (Value[I] <> '0') and (Value[I] <> '1') then
NotValidOfIntegerException;

// calculate
for I := S to Len do
Result := Result + (Ord(Value[I]) - Ord('0')) shl (Len - I);
if Negative then
Result := 0 - Result;
end;

//  simple and naive conversion function, though the fractal part is OK with the standard
//  not IEEE X compatible as the integer part is considered as simple integer
//  in IEEE standards the integral part should be exponentially calculated and not converted into decimal
function BinaryToDouble(const Value: string): Double;

procedure NotValidBinaryOfDoubleException;
begin
raise Exception.Create('BinaryToDouble Error : ''' + Value + ''' is not valid binary double');
end;

var
I, P, Len: Integer;
IntPart: string;
Temp: Double;
begin
//  Check validity and set boundaries
Result := 0;
Len := Length(Value);
if Len = 0 then
Exit;
P := Pos('.', Value);
if (P = 1) or (P = Len) then
NotValidBinaryOfDoubleException;
SetLength(IntPart, P - 1);
for I := 1 to P - 1 do
IntPart[I] := Value[I];
for I := P + 1 to Len do
if (Value[I] <> '0') and (Value[I] <> '1') then
NotValidBinaryOfDoubleException;

// calculate fractal part
if P > 0 then
begin
Inc(P);
Temp := 1 / 2;
for I := P to Len do
begin
Result := Result + Temp * (Ord(Value[I]) - Ord('0'));
Temp := Temp / 2;
end;
end;

// build final result
if Value = '-' then
Result := 0 - Result;
Result := Result + BinaryToInt(IntPart);
end;

begin
Writeln(DoubleToBin(582.24, 16));
Writeln(DoubleToBin(582.24,0, 2));
Writeln(DoubleToBin(-582.24, 0, 32));
Writeln(DoubleToBin(-10/3,0,24));

Writeln(FloatToStr(BinaryToDouble('-11.010101010101010101010101')));
Writeln(FloatToStr(BinaryToDouble('0000001001000110.00111101')));
Writeln(FloatToStr(BinaryToDouble('1001000110.00')));
Writeln(FloatToStr(BinaryToDouble('-1001000110.00111101011100001010001111010111')));

end.```

the result

```0000001001000110.00111101
1001000110.00
-1001000110.00111101011100001010001111010111
-11.010101010101010101010101
-3.33333331346512
582.23828125
582
-582.239999999991```

Hope you find it useful and for your quest after converting the fractal part then it is way simple that what you think, start with 1/2 and half it with each step, waling the bit from the left to the right.

ps : not fully tested but i think i mostly got it right at first try, if anyone find bug or have better and enhanced version of it or any other, please share here.

Ummm. I must be missing some deeper meaning here but what is the point of pretending that an integer values isn't already stored in binary format? I mean, I could understand if you were trying to implement bin/dec conversion on a denary computer but other than that this sounds like an algorithm for people that doesn't have access to computers.

• 1

8 hours ago, dummzeuch said:

Hm, I always convert to hex as an intermediary step (and actually prefer hex constants in source code). and I can still do binary to hex and back in my head, back from the C64 times.

Thanks, that was also pointed out by others online and it will likely be in a follow-up article.  I simply didn't know about the double-dabble trick and thought it was kinda cool.  I don't do these number system conversions enough to be able to convert any lengthy amount in my head yet.  Lately I've been attempting to spend a lot more time learning rather than just always doing.  Unfortunately, I was always the work-harder and not the work-smarter type.  Few could out-work me, but many could out-smart me.  I want to combine the two, and maybe the next buyout will have an extra zero or two behind it.  Or, I'll simply enjoy it more.  Either way, it's a win.

5 hours ago, Kas Ob. said:

I have mountain of things that need to be done right now, but what to say !, i am bored to hell and looking something to do away from what is needed, so.

@Darian Miller this is special for you

Literally LOL.  Thanks.  I'll try to absorb it!   🙂

@Darian Miller Just for fun

JUST FOUND NO BRACKET IN MY SOURCE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

what an HTML PAGE !!!!! plz fix

x:= StrToInt(s); <<<<<<<<<<<<  cannot put bracket i

unit Unit1;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, JvExStdCtrls, JvEdit,

type
TForm1 = class(TForm)
Button1: TButton;
JvValidateEdit1: TJvValidateEdit;
Label1: TLabel;
Button2: TButton;
JvValidateEdit2: TJvValidateEdit;
Label2: TLabel;
Button3: TButton;
JvValidateEdit3: TJvValidateEdit;
JvSpinEdit1: TJvSpinEdit;
Label3: TLabel;
Button4: TButton;
Label4: TLabel;
Label5: TLabel;
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{\$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
end;

procedure TForm1.Button1Click(Sender: TObject); //to binary
var
i,x:integer;
ans:string;
begin
ans:='';
i:=  JvValidateEdit1.Value;
while i>0 do
begin
ans:=IntToStr(i mod 2) + ans ;
i :=i div 2;
//ans:=IntToStr(i mod 2)+ans ;
//i :=i div 2;
end;
Label1.Caption:=ans;
end;

procedure TForm1.Button2Click(Sender: TObject); //  to decimal
var
s:string;
i,ans:Integer;
begin
ans:=1;
s:=JvValidateEdit2.Text;
for I := 1 to length(s)-1 do
ans:=(ans*2) +StrToInt(s[i+1]);
Label2.Caption:=IntToStr(ans);
end;

procedure TForm1.Button3Click(Sender: TObject);  //fraction cal
var
f:real;
i,x:integer ;
ans:string;
begin
ans:='0.';
f:=JvValidateEdit3.Value;
for I := 1 to Round(JvSpinEdit1.Value) do
begin
f:=f*2;
x:=Trunc(f);
f:=Frac(f);
ans:=ans+IntToStr(x);
end;
Label3.Caption:=ans;
end;

procedure TForm1.Button4Click(Sender: TObject); //binary to fruction
var
s:string;
k:Real;
i,x:Integer;
ans:string;
begin
k:=0;
s:=Edit1.Text;
for I :=Length(s) downto   1 do
begin
x:= StrToInt(s);
k:=(1/2)*(x+k);
end;
Label5.Caption:=FloatToStr(k);
end;

end.

object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 283
ClientWidth = 552
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 120
TextHeight = 16
object Label1: TLabel
Left = 335
Top = 35
Width = 37
Height = 19
Caption = 'Label1'
end
object Label2: TLabel
Left = 335
Top = 73
Width = 37
Height = 16
Caption = 'Label2'
end
object Label3: TLabel
Left = 335
Top = 119
Width = 27
Height = 16
Caption = 'anse'
end
object Label4: TLabel
Left = 187
Top = 155
Width = 16
Height = 21
Caption = '0.'
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -17
Font.Name = 'Tahoma'
Font.Style = [fsBold]
ParentFont = False
end
object Label5: TLabel
Left = 335
Top = 159
Width = 27
Height = 16
Caption = 'anse'
end
object Button1: TButton
Left = 66
Top = 32
Width = 110
Height = 25
Caption = 'To Binary'
TabOrder = 0
OnClick = Button1Click
end
object JvValidateEdit1: TJvValidateEdit
Left = 182
Top = 32
Width = 121
Height = 24
CriticalPoints.MaxValueIncluded = False
CriticalPoints.MinValueIncluded = False
EditText = '582'
TabOrder = 1
end
object Button2: TButton
Left = 68
Top = 70
Width = 108
Height = 25
Caption = 'To Decimal'
TabOrder = 2
OnClick = Button2Click
end
object JvValidateEdit2: TJvValidateEdit
Left = 182
Top = 70
Width = 121
Height = 24
CriticalPoints.MaxValueIncluded = False
CriticalPoints.MinValueIncluded = False
EditText = '1001000110'
TabOrder = 3
end
object Button3: TButton
Left = 66
Top = 116
Width = 110
Height = 25
Caption = 'Fruction Calc'
TabOrder = 4
OnClick = Button3Click
end
object JvValidateEdit3: TJvValidateEdit
Left = 182
Top = 117
Width = 121
Height = 24
CriticalPoints.MaxValueIncluded = False
CriticalPoints.MinValueIncluded = False
DisplayFormat = dfFloat
DecimalPlaces = 10
EditText = '0.24'
TabOrder = 5
end
object JvSpinEdit1: TJvSpinEdit
Left = 481
Top = 116
Width = 63
Height = 24
MaxValue = 10.000000000000000000
MinValue = 1.000000000000000000
Value = 8.000000000000000000
TabOrder = 6
end
object Button4: TButton
Left = 73
Top = 155
Width = 108
Height = 25
Caption = 'Binary Fruction'
TabOrder = 7
OnClick = Button4Click
end
object Edit1: TEdit
Left = 208
Top = 155
Width = 95
Height = 24
NumbersOnly = True
TabOrder = 8
Text = '1011'
end
end

Edited by limelect

@limelect Press to insert code without having the editor destroying it.

@Lars Fosdal This is a test

</> [my test]

Nice now I understand

So if I put source I </> before the source right?

Edited by limelect

2 hours ago, limelect said:

@Lars Fosdal﻿ So if I put source I </> before the source right?

Take a look above the text editor, in the toolbar and look for the </> button, press that to insert code 🙂

Thanks OK