{$MODE OBJFPC}
{$LONGSTRINGS ON}
{$IFDEF WINDOWS}
{$APPTYPE CONSOLE}
{$ENDIF}
uses SysUtils, DateUtils;
type
TDecimalLength64 = function(AValue: QWord): Integer;
var
GValues64: array of QWord = nil;
procedure Measure64(Func: TDecimalLength64; const Desc: string);
const
CTimes = 1000;
var
i: SizeInt;
Start: TDateTime;
Value: QWord;
begin
Write(Desc, '': 30 - Length(Desc));
Start := Time;
for i := 1 to CTimes do
for Value in GValues64 do
Func(Value);
WriteLn(MilliSecondsBetween(Start, Time), ' msec');
end;
procedure InitGValues64;
const
CCount = 10000;
var
i: SizeInt;
begin
Randomize;
SetLength(GValues64, CCount);
for i := 0 to CCount - 1 do
GValues64[i] := Random(High(Int64));
end;
{ Bytebits }
function BytebitsDecLenIf(i: QWord): Integer;
begin
if i<10000000 then
if i<10 then exit( 1 )
else if i<100 then exit( 2 )
else if i<1000 then exit( 3 )
else if i<10000 then exit( 4 )
else if i<100000 then exit( 5 )
else if i<1000000 then exit( 6 )
else exit( 7 )
else if i<10000000000000 then
if i<100000000 then exit( 8 )
else if i<1000000000 then exit( 9 )
else if i<10000000000 then exit( 10 )
else if i<100000000000 then exit( 11 )
else if i<1000000000000 then exit( 12 )
else exit( 13 )
else if i<100000000000000 then exit( 14 )
else if i<1000000000000000 then exit( 15 )
else if i<10000000000000000 then exit( 16 )
else if i<100000000000000000 then exit( 17 )
else if i<1000000000000000000 then exit( 18 )
else if i<10000000000000000000 then exit( 19 )
else exit( 20 );
end;
{ Jamie }
function JamieHowManyDigits(aInput:QWord): Integer;
begin
Result:=1;
While aInput > 9 do
begin
Inc(Result);
aInput := aInput div 10;
end;
end;
{ Keys }
function KeysDecimalDigitCount(n: QWord): Integer;
begin
Result := Trunc(Ln(n + Ord(n = 0)) / Ln(10)) + 1;
end;
{ LemonParty }
function LemonPartyDecimalLength32(u: UInt32): Integer; inline;
const
CTable: array [0..32] of UInt64 = (
4294967296,
4294967296, 8589934582, 8589934582, 8589934582,
12884901788, 12884901788, 12884901788, 17179868184,
17179868184, 17179868184, 21474826480, 21474826480,
21474826480, 21474826480, 25769703776, 25769703776,
25769703776, 30063771072, 30063771072, 30063771072,
34349738368, 34349738368, 34349738368, 34349738368,
38554705664, 38554705664, 38554705664, 41949672960,
41949672960, 41949672960, 42949672960, 42949672960
);
begin
Result:= ( u + CTable[ UInt8( BsrDWord( u )+1 ) ] ) shr 32;
end;
function LemonPartyDecimalLength64(u: QWord): Integer;
begin
if u <= High(UInt32) then
Result:= LemonPartyDecimalLength32(UInt32(u))
else case u of
High(UInt32)+1..9999999999: Result:= 10;
10000000000..99999999999: Result:= 11;
100000000000..999999999999: Result:= 12;
1000000000000..9999999999999: Result:= 13;
10000000000000..99999999999999: Result:= 14;
100000000000000..999999999999999: Result:= 15;
1000000000000000..9999999999999999: Result:= 16;
10000000000000000..99999999999999999: Result:= 17;
100000000000000000..999999999999999999: Result:= 18;
1000000000000000000..9999999999999999999: Result:= 19;
else Result:= 20;
end;
end;
{ Josh }
function JoshBitLength64(n:QWord): Integer; inline;
const
deBruijn64:array[0..63] of Byte=(0,1,2,53,3,7,54,27,4,38,41,8,34,55,48,28,62,5,39,46,44,42,22,9,24,35,59,56,49,18,29,11,63,52,6,26,37,40,33,47,61,45,43,21,23,58,17,10,51,25,36,32,60,20,57,16,50,31,19,15,30,14,13,12);
var t:QWord;
begin
t:=n;
t:=t or (t shr 1);
t:=t or (t shr 2);
t:=t or (t shr 4);
t:=t or (t shr 8);
t:=t or (t shr 16);
t:=t or (t shr 32);
Result:=deBruijn64[((t-(t shr 1))*$022FDD63CC95386D) shr 58]+1;
end;
function JoshDecimalLength64(n:QWord): Integer;
const
POW10_64:array[0..19] of QWord=(1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000,100000000000,1000000000000,10000000000000,100000000000000,1000000000000000,10000000000000000,100000000000000000,1000000000000000000,10000000000000000000);
var bits,guess:LongInt;
begin
if n<10 then Exit(1);
bits:=JoshBitLength64(n);
guess:=(bits*1233) shr 12;
if n>=POW10_64[guess] then Inc(guess);
Result:=guess;
end;
{ Thaddy }
function ThaddyDecLength(i: QWord): Integer;
begin
case i of
0..9:result := 1;
10..99: result := 2;
100..999:result := 3;
1000..9999:result := 4;
10000..99999:result := 5;
100000..999999:result := 6;
1000000..9999999:result := 7;
10000000..99999999:result := 8;
100000000..999999999:result := 9;
1000000000..9999999999:result := 10;
10000000000..99999999999:result := 11;
100000000000..999999999999:result := 12;
1000000000000..9999999999999:result := 13;
10000000000000..99999999999999:result := 14;
100000000000000..999999999999999:result := 15;
1000000000000000..9999999999999999:result := 16;
10000000000000000..99999999999999999:result := 17;
100000000000000000..999999999999999999:result := 18;
1000000000000000000..9999999999999999999:result := 19
else result := 20;
end;
end;
begin
InitGValues64;
Measure64(@LemonPartyDecimalLength64, 'LemonPartyDecimalLength64');
Measure64(@ByteBitsDecLenIf, 'ByteBitsDecLenIf');
Measure64(@JoshDecimalLength64, 'JoshDecimalLength64');
Measure64(@ThaddyDecLength, 'ThaddyDecLength');
Measure64(@JamieHowManyDigits, 'JamieHowManyDigits');
Measure64(@KeysDecimalDigitCount, 'KeysDecimalDigitCount');
Writeln;
Write('Press Enter to close...');
Readln;
end.