Increment a numerical string: Difference between revisions

Content added Content deleted
m (→‎{{header|Pascal}}: don't change a standard type word == Uint16 into a string[20] added example output)
m (Move 'Free Pascal' as subtype of Pascal)
Line 1,419: Line 1,419:
777.77 + 1 = 778.77
777.77 + 1 = 778.77
1000 + 1 = 1001
1000 + 1 = 1001
</pre>

=={{header|Free Pascal}}==
not like [[#Delphi|Delphi]] doing two conversion, but increment a string by 1 is much faster.
Here with different bases upto 10.After this there must be a correction to convert values > '9' to 'A'...
Only for positive integer strings as high speed counter.
<lang pascal>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
repeat
dg := ord(ps[le])+(-ord('0')+1);
result := -ord(dg>=base);// -1 or 0 -> $FF...FF or $00...00
ps[le] := chr(-(result AND base)+dg+ord('0'));
dec(le);
until (result = 0) or (le<0);
end;

procedure IncIntStr(base:NativeInt;var s:myString);
begin
//overflow -> prepend a '1' to string
if (IncLoop(pChar(@s[1]),length(s),base) <>0) then
s := '1'+s;
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.
</lang>
{{out|@TIO.RUN}}
<pre>
67108863 increments in base
11111111111111111111111111 base 2 0.451 s
11200021111001110 base 3 0.394 s
3333333333333 base 4 0.339 s
114134440423 base 5 0.363 s
10354213103 base 6 0.358 s
1443262443 base 7 0.320 s
377777777 base 8 0.310 s
150244043 base 9 0.308 s
67108863 base 10 0.301 s // without inline 0.364

One billion digits "9"
first 5 digits 09999
1000000001 1.813 s
first 5 digits 10000
</pre>
</pre>


Line 2,482: Line 2,377:
{{out}}
{{out}}
<pre>12345 turns into 12346</pre>
<pre>12345 turns into 12346</pre>
==={{header|Free Pascal}}===
not like [[#Delphi|Delphi]] doing two conversion, but increment a string by 1 is much faster.
Here with different bases upto 10.After this there must be a correction to convert values > '9' to 'A'...
Only for positive integer strings as high speed counter.
<lang pascal>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
repeat
dg := ord(ps[le])+(-ord('0')+1);
result := -ord(dg>=base);// -1 or 0 -> $FF...FF or $00...00
ps[le] := chr(-(result AND base)+dg+ord('0'));
dec(le);
until (result = 0) or (le<0);
end;


procedure IncIntStr(base:NativeInt;var s:myString);
begin
//overflow -> prepend a '1' to string
if (IncLoop(pChar(@s[1]),length(s),base) <>0) then
s := '1'+s;
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.
</lang>
{{out|@TIO.RUN}}
<pre>
67108863 increments in base
11111111111111111111111111 base 2 0.451 s
11200021111001110 base 3 0.394 s
3333333333333 base 4 0.339 s
114134440423 base 5 0.363 s
10354213103 base 6 0.358 s
1443262443 base 7 0.320 s
377777777 base 8 0.310 s
150244043 base 9 0.308 s
67108863 base 10 0.301 s // without inline 0.364

One billion digits "9"
first 5 digits 09999
1000000001 1.813 s
first 5 digits 10000
</pre>
=={{header|Perl}}==
=={{header|Perl}}==
<lang perl>my $s = "12345";
<lang perl>my $s = "12345";