98 lines
2.0 KiB
ObjectPascal
98 lines
2.0 KiB
ObjectPascal
program StrInc;
|
|
//increments a positive numerical string in different bases.
|
|
//the string must be preset with a value, length >0 ;
|
|
{$IFDEF WINDOWS}
|
|
{$APPTYPE CONSOLE}
|
|
{$ENDIF}
|
|
{$IFDEF FPC}
|
|
{$Mode Delphi} {$Optimization ON,ALL}{$Align 32}
|
|
uses
|
|
sysutils;
|
|
{$ELSE}
|
|
uses
|
|
system.SysUtils;
|
|
{$ENDIF}
|
|
type
|
|
myString = AnsiString; // String[32];//
|
|
|
|
function IncLoop(ps: pChar;le,Base: NativeInt):NativeInt;inline;
|
|
//Add 1 and correct carry
|
|
//returns 0, if no overflow, else 1
|
|
var
|
|
dg: nativeInt;
|
|
Begin
|
|
dec(le);//ps is 0-based
|
|
dg := ord(ps[le])+(-ord('0')+1);
|
|
result := 0;
|
|
|
|
repeat
|
|
IF dg < base then
|
|
begin
|
|
ps[le] := chr(dg+ord('0'));
|
|
EXIT;
|
|
end;
|
|
ps[le] := '0';
|
|
dec(le);
|
|
dg := ord(ps[le])+(-ord('0')+1);
|
|
until (le<0);
|
|
result:= 1;
|
|
end;
|
|
|
|
procedure IncIntStr(base:NativeInt;var s:myString);
|
|
var
|
|
le: NativeInt;
|
|
begin
|
|
le := length(s);
|
|
//overflow -> prepend a '1' to string
|
|
if (IncLoop(pChar(@s[1]),le,base) <>0) then
|
|
Begin
|
|
// s := '1'+s;
|
|
setlength(s,le+1);
|
|
move(s[1],s[2],le);
|
|
s[1] := '1';
|
|
end;
|
|
end;
|
|
|
|
const
|
|
ONE_BILLION = 1000*1000*1000;
|
|
strLen = 26;
|
|
MAX = 1 shl strLen -1;
|
|
|
|
var
|
|
s : myString;
|
|
i,base : nativeInt;
|
|
T0: TDateTime;
|
|
Begin
|
|
writeln(MAX,' increments in base');
|
|
For base := 2 to 10 do
|
|
Begin
|
|
//s := '0' doesn't work
|
|
setlength(s,1);
|
|
s[1]:= '0';
|
|
{ //Zero pad string
|
|
setlength(s,strLen);fillchar(s[1],strLen,'0');
|
|
}
|
|
T0 := time;
|
|
For i := 1 to MAX do
|
|
IncIntStr(Base,s);
|
|
T0 := (time-T0)*86400;
|
|
writeln(s:strLen,' base ',base:2,T0:8:3,' s');
|
|
end;
|
|
|
|
writeln;
|
|
writeln('One billion digits "9"');
|
|
setlength(s,ONE_BILLION+1);
|
|
s[1]:= '0';//don't measure setlength in IncIntStr
|
|
fillchar(s[2],length(s)-1,'9');
|
|
writeln('first 5 digits ',s[1],s[2],s[3],s[4],s[5]);
|
|
T0 := time;
|
|
IncIntStr(10,s);
|
|
T0 := (time-T0)*86400;
|
|
writeln(length(s):10,T0:8:3,' s');
|
|
writeln('first 5 digits ',s[1],s[2],s[3],s[4],s[5]);
|
|
s:='';
|
|
{$IFDEF WINDOWS}
|
|
readln;
|
|
{$ENDIF}
|
|
end.
|