You are on page 1of 68

How to calculate the week number

2001-04-27 19:44:57 mailto:info@delphitips.comGustav Evertsson Ratings: 0, Votes: 0


There are 2 other functions included which are required for our function. One checks for a
Leap year, the other returns the # of days in a month (checking the leap year) and the 3rd
is the one you want, the week of the year.

function IsLeapYear( nYear: Integer ): Boolean;


begin
Result := (nYear mod 4 = 0) and ((nYear mod 100 <> 0) or (nYear mod 400 = 0));
end;

function MonthDays( nMonth, nYear: Integer ): Integer;


const
DaysPerMonth: array[1..12] of Integer = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
begin
Result := DaysPerMonth[nMonth];
if (nMonth = 2) and IsLeapYear(nYear) then Inc(Result);
end;

function WeekOfYear( dDate: TDateTime ): Integer;


var
X, nDayCount: Integer;
nMonth, nDay, nYear: Word;
begin
nDayCount := 0;
deCodeDate( dDate, nYear, nMonth, nDay );
For X := 1 to ( nMonth - 1 ) do
nDayCount := nDayCount + MonthDays( X, nYear );
nDayCount := nDayCount + nDay;
Result := ( ( nDayCount div 7 ) + 1 );
end;

1
...decode a TDate type ?
Author: SwissDelphiCenter.ch

procedure TForm1.Button4Click(Sender: TObject);


const
Year, Month, Day : Word;
begin
// Date = 12/12/2001
DecodeDate(Date,Year,Month,Day);
label1.Caption := IntToStr(Year); // 2001
label2.Caption := IntToStr(Month); // 12
label3.Caption := IntToStr(Day); // 12
end;

2
...convert Hex codes ?
Author: SwissDelphiCenter.ch

procedure TForm1.Button1Click(Sender: TObject);


begin
Label1.Caption:=inttostr(strtoint('$AFFE')); //45054
end;

3
...get the difference between 2 dates ?
Author: SwissDelphiCenter.ch

procedure TForm1.Button1Click(Sender: TObject);


var
date1,
date2 :TDateTime;
difference:integer;
begin
date1:=EncodeDate(2000,06,15); //Date 2000/06/15
date2:=EncodeDate(2000,01,01); //Date 2000/01/01

difference:=trunc(date1-date2);
ShowMessage(inttostr(difference));
end;

4
...get the week number of a date ?
Author: unknown

var
FirstWeekDay : Integer = 2;
{ Wochentag, mit dem die Woche beginnt
(siehe Delphi-Wochentage)
2 : Montag (nach DIN 1355) }
FirstWeekDate : Integer = 4;
{ 1 : Beginnt am ersten Januar
4 : Erste-4 Tage-Woche (nach DIN 1355)
7 : Erste volle Woche }

{ liefert das Datum des ersten Tages der Woche }


{ get date of first day of week}
function WeekToDate(AWeek,AYear:Integer):TDateTime;
begin
Result:=EncodeDate(AYear,1,FirstWeekDate);
Result:=Result+(AWeek-1)*7-((DayOfWeek(Result)+(7-FirstWeekDay)) mod 7);
end;

{ liefert die Wochennummer und das Jahr, zu dem die Woche geh rt }
{ get weeknumber and year of the given week number}
procedure DateToWeek(ADate:TDateTime; var AWeek,AYear:Word);
var
Month,Day : Word;
begin
ADate:=ADate-((DayOfWeek(ADate)-FirstWeekDay+7) mod 7)+ 7-FirstWeekDate;
DecodeDate(ADate,AYear,Month,Day);
AWeek:=(Trunc(ADate-EncodeDate(AYear,1,1)) div 7)+1;
end;

{Week to date example}


procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(FormatDateTime('dd.mm.yyyy',WeekToDate(51,2000)));
end;

{Date to week example}


procedure TForm1.Button2Click(Sender: TObject);
var
week,year:Word;
begin
DateToWeek(now,week,year);
ShowMessage(inttostr(week));
ShowMessage(inttostr(year));
end;

5
...get the last day of the current month ?
Author: Fred

function LastDayOfCurrentMonth: TDate;


var
y, m, d: word;
begin
decodedate(now, y, m, d);
m := m + 1;
if m > 12 then
begin
y := y + 1;
m := 1;
end;
result := encodedate(y, m, 1) - 1;
end;

procedure TForm1.Button1Click(Sender: TObject);


begin
ShowMessage(DateToStr(LastDayOfCurrentMonth));
end;

6
a shorter way to do get the last day of the current month
Author: Henk Schreij

function LastDayOfMonth(Dat: TDate): TDate;


var
D, M, Y: Word;
begin
DecodeDate(IncMonth(Dat, 1), Y, M, D);
Result:= EncodeDate(Y, M, 1) - 1;
end;

//Use a Button, Label and DateTimePicker for testing:


procedure TForm1.Button1Click(Sender: TObject);
begin
Label1.Caption := FormatDateTime('d-m-yyyy',LastDayOfMonth
(DateTimePicker1.Date));
end;

Even less code


Author: Henk Pieters
function LastDayOfCurrentMonth: TDate;
begin
result := incMonth(now,1)- 1;
end;

7
...use TTime with over 24 hours ?
Author: Zandy

function TextToTime(S: string): integer;


var
p, i: integer;
Sh, Sm, Ss: string;
begin
Sh := '';
SM := '';
SS := '';
i := 1;
p := 0;
while i <= length(s) do
begin
if (s[i] <> ':') then
begin
case P of
0: SH := Sh + s[i];
1: SM := SM + S[i];
2: SS := SS + S[i];
end;
end
else
inc(p);
inc(i);
end;
try
Result := (StrToInt(SH) * 3600) + (StrToInt(SM) * 60) + (StrToInt(SS))
except
Result := 0;
end;
end;

function TimeToText(T: integer): string;


var
H, M, S: string;
ZH, ZM, ZS: integer;
begin
ZH := T div 3600;
ZM := T div 60 - ZH * 60;
ZS := T - (ZH * 3600 + ZM * 60);
if ZH < 10 then
H := '0' + IntToStr(ZH)
else
H := IntToStr(ZH);
if ZM < 10 then
M := '0' + IntToStr(ZM)
else
M := IntToStr(ZM);
if ZS < 10 then
S := '0' + IntToStr(ZS)
else
S := IntToStr(ZS);
Result := H + ':' + M + ':' + S;
end;

8
..convert a Binary Number into a Decimal Number ?
Author: tom

function BinToInt(Value: String): Integer;


var
i, iValueSize: Integer;
begin
Result := 0;
iValueSize:= Length(Value);
for i:= iValueSize downto 1 do
if Value[i] = '1' then Result := Result+(1 shl (iValueSize-i));
end;

procedure TForm1.Button1Click(Sender: TObject);


begin
ShowMessage(Inttostr(BinToInt('010101')));
end;

9
...calculate simple arithmetical expressions ?
Author: tom

function Calculate(SMyExpression: string; digits : Byte): string;


// Calculate a simple expression
// Supported are: Real Numbers, parenthesis
var
z: char;
ipos : integer;

function StrToReal(InStr: String): real;


var
Code : Integer;
Temp : Real;
begin
STRtoREAL:= 0;
If Copy(InStr,1,1)='.' then
InStr:= '0' + InStr;
If (Copy(InStr,1,1)='-') and (Copy(InStr,2,1)='.') then
Insert('0',InStr,2);
If InStr[length(InStr)] = '.' then
Delete(InStr,length(InStr),1);
Val(InStr,Temp,Code);
if Code = 0 then
STRtoREAL:= Temp;
end;

function RealToStr(inreal: extended; digits : byte): string;


var
S: string;
begin
Str(inreal: 0: digits, S);
realToStr := S;
end;

procedure NextChar;
var
s: string;
begin
if ipos > length(SMyExpression) then
begin
z := #9;
exit;
end
else
begin
s := copy(SMyExpression, ipos, 1);
z := s[1];
inc(ipos);
end;
if z = ' ' then
nextchar;
end;

10
function Expression: real;
var
w: real;

function Factor: real;


var
ws: string;
begin
Nextchar;
if z in ['0'..'9'] then
begin
ws := '';
repeat
ws := ws + z;
nextchar
until not (z in ['0'..'9', '.']);
Factor := StrToReal(ws);
end
else if z = '(' then
begin
Factor := Expression;
nextchar
end
else if z = '+' then Factor := +Factor
else if Z = '-' then Factor := -Factor;
end;

function Term: real;


var
W: real;
begin
W := Factor;
while Z in ['*', '/'] do
if z = '*' then
w := w * Factor
else
w := w / Factor;
Term := w;
end;

begin
w := term;
while z in ['+', '-'] do
if z = '+' then
w := w + term
else
w := w - term;
Expression := w;
end;

begin
ipos := 1;
Result := RealToStr(Expression,digits);
end;

11
procedure TForm1.Button1Click(Sender: TObject);
Var
sMyExpression : string;
begin
sMyExpression := '12.5*6+18/3.2+2*(5-6.23)';
ShowMessage(sMyExpression + ' = '+ Calculate(sMyExpression,3));
end;

12
...measure an elapsed time with a high-resolution performance counter ?
Author: Gstatter, Erhard

//Example, Beispiel:

You want to measure the elapsed time in a Repeat, While or a For-Loop


to do some optimation ?

Sie m chten eine Routine mit einer Repeat, While oder For i := ...
hinsichtlich der
durchlaufenen Zeit messen, um z. B. Optimierungsaktivit ten durchzufhren.

// Global Variables, Globale Variablen:


t1, t2, Res : TLargeInteger; // In Windows.pas deklariert
bOk : BOOL;

implementation
uses Windows, dialogs;
Procedure StartTimer;
Begin
bOK := QueryPerformanceFrequency(Res);
IF bOK THEN
QueryPerformanceCounter(t1);
end;
Procedure StopTimer;
Begin
IF bOK THEN
QueryPerformanceCounter(t2);
end;
Procedure LoopRoutine;
VAR
iCounter : integer;
Begin
StartTimer;
// Put here some kind of loop: For, While or Repeat
FOR i := 0 TO iCounter DO ...
{ WHILE....
repeat...until}
{ After the Loop/
Nach Abschluss der Schleifenroutine:}
IF bOK THEN
QueryPerformanceCounter(t2);
end;
Procedure StartSchleife;
Begin
LoopRoutine;
IF bOK THEN
{$IFDEF VER80}
// Show the elapsed time:
MessageDlg('Der Schleifendurchlauf dauerte: '+Format('%g Sekunden.',
[(t2.QuadPart-t1.Quadpart)/Res.QuadPart]));
$ELSE {$IFDEF VER120}
MessageDlg('Der Schleifendurchlauf dauerte: '+Format('%g Sekunden.',
[(t2-t1)/Res]));
{$ENDIF}
end;

...is a Time AM or PM ?

13
Author: --
procedure AM_or_PM;
begin
if(Frac(Time) < 0.5) then
ShowMessage('AM')
else
ShowMessage('PM');
end;

14
...Get the number of the day in the year ?
Author: SwissDelphiCenter.ch

function GetDays(ADate: TDate): Extended;


var
FirstOfYear: TDateTime;
begin
FirstOfYear:=EncodeDate(StrToInt(FormatDateTime('yyyy',now))-1,12,31);
Result:=ADate-FirstOfYear;
end;

procedure TForm1.Button1Click(Sender: TObject);


begin
Label1.Caption:='Today is the '+FloatToStr(GetDays(Date))+'. day of the
year';
end;

15
...round a number correctly ?
Author: SwissDelphiCenter.ch

{The function Round of the Delphi doesn't work


like it is usually expected.
The odd numbera are rounded down and the even numbers up.

Die Round Funktion in Delphi gibt normalerweise nicht


die erwartete Zahl zurck.
Die ungeraden Zahlen werden abgerundet, die geraden
aufgerundet

Example/ Beispiel:
x:= Round(17.5) => x = 18

x:= Round(12.5) => x = 12


}
function MyRound(Const X: Extended): Int64;
begin
Result:= Trunc(X);
if (Frac(X) >= 0.5) then
Result:= Result + 1;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(FormatFloat('0.00',MyRound(17.5))); // -> 18
ShowMessage(FormatFloat('0.00',MyRound(12.5))); // -> 13
//This rounds every value to 0.05 steps
//Rundet in 0.05 Schritten
ShowMessage(FormatFloat('0.00',Round(17.22/0.05)*0.05)); // -> 17.20
end;
{***Another function:***}
function RoundUp(Value: Extended): Int64;
procedure Set8087CW(NewCW: Word);
asm
MOV Default8087CW,AX
FNCLEX
FLDCW Default8087CW
end;
const
RoundUpCW = $1B32;
var
OldCW: Word;
begin
OldCW := Default8087CW;
try
Set8087CW(RoundUpCW);
result := Round(Value);
finally
Set8087CW(OldCW);
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
ShowMessage(FormatFloat('0.00',RoundUp(19.32))); // -> 19
end;

...convert a hexadecimal number into a Integer ?

16
Author: tom
function StrToHex(s : string) : LongWord;
var
b : Byte;
c : Char;
begin
Result := 0;
s := UpperCase(s);
for b := 1 to Length(s) do
begin
Result := Result * 16;
c := s[b];
case c of
'0'..'9': Inc(Result, ord(c) - ord('0'));
'A'..'F': Inc(Result, ord(c) - ord('A')+10);
else raise EConvertError.Create('Keine Hexadezimal-Zahl');
end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);


begin
ShowMessage(IntToStr(StrToHex('AAF1'))); // > 43761
end;

17
... encrypt text using key numbers?
Author: Rafael Giusti

{This two functions are used to encrypt and decrypt text.


Here's how to use it:
The four entries Key1, Key2, Key3 and Key4 are numbers
that can range from 1 to 120. In order to decrypt a text,
you must use the same numbers you used to encrypt the text.
No one that doesn't know what values were used on Key1, Key2, Key3 and Key4
will be able to decrypt your text!
Note that Key1*Key4 MUST be different than Key2*Key3.
If any Key is zero, or Key1*Key4 is equal to Key2*Key3,
the function will return ''.
In Brief:
Key1, Key2, Key3, Key4 : integer from range[1..120]
Key1*Key4 <> Key2*Key3
}

function Encrypt(Text : string; Key1, Key2, Key3, Key4 : Integer) : string;


var
BufS, Hexa, Hexa1, Hexa2 : string;
BufI, BufI2, Sc, Sl, Num1, Num2, Num3, Num4, Res1, Res2, Res3, Res4 :
Integer;
begin
Sl := Length(Text);
Sc := 0;
BufS := '';
if (Key1 in [1 .. 120]) and (Key2 in [1 .. 120]) and (Key3 in [1 .. 120])
and (Key4 in [1 .. 120]) then
begin
BufI := Key1 * Key4;
BufI2 := Key3 * Key2;
BufI := BufI - BufI2;
if BufI = 0 then
begin
Result := '';
Exit;
end;
end
else
begin
Result := '';
Exit;
end;
repeat
Inc(Sc);
if Sc > Sl then Num1 := 0 else Num1 := Ord(Text[Sc]);
Inc(Sc);
if Sc > Sl then Num2 := 0 else Num2 := Ord(Text[Sc]);
Inc(Sc);
if Sc > Sl then Num3 := 0 else Num3 := Ord(Text[Sc]);
Inc(sc);
if Sc > Sl then Num4 := 0 else Num4 := Ord(Text[Sc]);
Res1 := Num1 * Key1;
BufI := Num2 * Key3;
Res1 := Res1 + BufI;
Res2 := Num1 * Key2;
BufI := Num2 * Key4;
Res2 := Res2 + BufI;
18
Res3 := Num3 * Key1;
BufI := Num4 * Key3;
Res3 := Res3 + BufI;
Res4 := Num3 * Key2;
BufI := Num4 * Key4;
Res4 := Res4 + BufI;
for BufI := 1 to 4 do
begin
case BufI of
1 : Hexa := IntToHex(Res1, 4);
2 : Hexa := IntToHex(Res2, 4);
3 : Hexa := IntToHex(Res3, 4);
4 : Hexa := IntToHex(Res4, 4);
end;
Hexa1 := '$' + Hexa[1] + Hexa[2];
Hexa2 := '$' + Hexa[3] + Hexa[4];
if (Hexa1 = '$00') and (Hexa2 = '$00') then
begin
Hexa1 := '$FF';
Hexa2 := '$FF';
end;
if Hexa1 = '$00' then Hexa1 := '$FE';
if Hexa2 = '$00' then
begin
Hexa2 := Hexa1;
Hexa1 := '$FD';
end;
BufS := BufS + Chr(StrToInt(Hexa1)) + Chr(StrToInt(Hexa2));
end;
until Sc >= Sl;
Result := BufS;
end;

function Decrypt(Text : string; Key1, Key2, Key3, Key4 : Integer) : string;


var
BufS, Hexa1, Hexa2 : string;
BufI, BufI2, Divzr, Sc, Sl, Num1, Num2, Num3, Num4, Res1, Res2, Res3, Res4
: Integer;
begin
Sl := Length(Text);
Sc := 0;
BufS := '';
if (Key1 in [1 .. 120]) and (Key2 in [1 .. 120]) and (Key3 in [1 .. 120])
and (Key4 in [1 .. 120]) then
begin
Divzr := Key1 * Key4;
BufI2 := Key3 * Key2;
Divzr := Divzr - BufI2;
if Divzr = 0 then
begin
Result := '';
Exit;
end;
end
else
begin
Result := '';
Exit;
end;
repeat
19
for BufI := 1 to 4 do
begin
Inc(Sc);
Hexa1 := IntToHex(Ord(Text[Sc]), 2);
Inc(Sc);
Hexa2 := IntToHex(Ord(Text[Sc]), 2);
if Hexa1 = 'FF' then
begin
Hexa1 := '00';
Hexa2 := '00';
end;
if Hexa1 = 'FE' then Hexa1 := '00';
if Hexa1 = 'FD' then
begin
Hexa1 := Hexa2;
Hexa2 := '00';
end;
case BufI of
1 : Res1 := StrToInt('$' + Hexa1 + Hexa2);
2 : Res2 := StrToInt('$' + Hexa1 + Hexa2);
3 : Res3 := StrToInt('$' + Hexa1 + Hexa2);
4 : Res4 := StrToInt('$' + Hexa1 + Hexa2);
end;
end;
BufI := Res1 * Key4;
BufI2 := Res2 * Key3;
Num1 := BufI - BufI2;
Num1 := Num1 div Divzr;
BufI := Res2 * Key1;
BufI2 := Res1 * Key2;
Num2 := BufI - BufI2;
Num2 := Num2 div Divzr;
BufI := Res3 * Key4;
BufI2 := Res4 * Key3;
Num3 := BufI - BufI2;
Num3 := Num3 div Divzr;
BufI := Res4 * Key1;
BufI2 := Res3 * Key2;
Num4 := BufI - BufI2;
Num4 := Num4 div Divzr;
BufS := BufS + Chr(Num1) + Chr(Num2) + Chr(Num3) + Chr(Num4);
until Sc >= Sl;
Result := BufS;
end;

20
...convert an Integer to an octal number ?
Author: Katja Hoffmann
Homepage: http://www.katjahoffmann.gmxhome.de
function IntToOct(value:longint; digits:integer):string;
var
rest : longint;
oct : string;
i : integer;
begin
oct := '';
while value > 0 do
begin
rest := value mod 8;
value := value div 8;
oct := inttostr(rest)+oct;
end;
for i := length(oct)+1 to digits do
oct := '0'+oct;
result := oct;
end;

21
...convert an octal number to integer ?
Author: Katja Hoffmann
Homepage: http://www.katjahoffmann.gmxhome.de
function OctToInt(value:string):longint;
var
i : integer;
int: integer;
begin
int:=0;
for i:=1 to length(value) do
begin
int:=int*8+strtoint(copy(value,i,1));
end;
result:=int;
end;

22
...round numbers to a predetermined number of decimals ?
Author: Dean

function Rounder(var Value: Double; Decimals: Integer): Double;


var
j: Integer;
A: Double;
begin
A:=1;
Case Decimals of
0 : A:=1;
1 : A:=10;
else
for j:=1 to Decimals do
A := A * 10;
end;
Result:=Int((Value * A) + 0.5) / A;
end;

procedure TForm1.Button1Click(Sender: TObject);


var
value: Double;
begin
value := 23.56784;
//Result is 23.57
Label1.Caption := FloatToStr(Rounder(value, 2));
end;

23
Its good, but, try this...
Author: Srgio Alexandre

It s my rounder routine, it s similar of clipper Round function:

Function Rounder(Value: Double; Dec: Integer): Double;


Var
Fat: Double;
Con: Integer;
Begin
Fat := 1;
For Con := 1 To Abs(Dec) Do
Fat := Fat * 10;
If Dec < 0 Then Fat := 1 / Fat;
Result := Round(Value * Fat) / Fat;
End;

24
...convert a decimal number to roman numerals ?
Author: Thomas Stutz
Homepage: http://www.swissdelphicenter.ch
function DecToRoman(Decimal: LongInt): String;
const
Numbers : Array[1..13] of Integer =
(1, 4, 5, 9, 10, 40, 50, 90, 100,
400, 500, 900, 1000);
Romans: Array[1..13] of string =
('I', 'IV', 'V', 'IX', 'X', 'XL',
'L', 'XC', 'C', 'CD', 'D', 'CM', 'M');
var
i: Integer;
begin
Result := '';
for i := 13 downto 1 do
while (Decimal >= Numbers[i]) do
begin
Decimal := Decimal - Numbers[i];
Result := Result + Romans[i];
end;
end;

//Example:
//Beispiel:

procedure TForm1.Button1Click(Sender: TObject);


begin
Label1.Caption := DecToRoman(5);
Label2.Caption := DecToRoman(458);
end;

25
...check if the Cursor is on a line ?
Author: Johannes Steiner

{
Check if a Point(X,Y) (e.g a Cursor) is on a Linie (x1,y1) ; (x2,y2)
d = line width (min. 1)

Testen, ob sich der Punkt(X,Y) (z.B der Maus-Cursor) auf der Linie x1,y1 nach
x2,y2 befindet.
d = halbe Liniendicke (min 1)
durch direkte Programmierung der FPU wird die Unit Math nicht ben tigt
nur mit 80387 oder h her einsetzbar!
}

function CursorOnLinie(X,Y,x1,y1,x2,y2,d: integer): boolean;


var
sine, cosinus: double;
dx,dy, len: integer;
begin
if d = 0 then d := 1;
asm
fild(y2)
fisub(y1) // Y-Difference
fild(x2)
fisub(x1) // X-Difference
fpatan // Angle of the line in st(0)
fsincos // Cosinus in st(0), Sinus in st(1)
fstp cosinus
fstp sine
end;
dx := Round(cosinus*(x-x1) + sine*(y-y1));
dy := Round(cosinus*(y-y1) - sine*(x-x1));
len := Round(cosinus*(x2-x1) + sine*(y2-y1)); // length of line
if (dy > -d) and (dy < d) and (dx > -d) and (dx < len+d)
then Result := true
else Result := false;
end;

procedure TForm1.FormPaint(Sender: TObject);


begin
Canvas.Pen.Width := 1;
Canvas.MoveTo(0,0);
Canvas.LineTo(Width,Weight);
end;

26
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
p : TPoint;
begin
GetCursorPos(p);
p := ScreenToClient(p);
if CursorOnLinie(p.x,p.y,0,0,Width,Height,1) then
Caption := 'Mouse on line.'
else
Caption := 'Mouse not on line.'
end;

27
...calculate the value of a polynomial at a given point ?
Author: Los Bgu
// Simultaneous evaluation of a given polynomial and its first derivative at
a given point
// Simultane Berechnung des Wertes eines Polynoms n-ten Grades und seiner
Ableitung

Type
TPolynomArray = Array of Double;

procedure Horner(Polynom: TPolynomArray; X: Extended; Var FX,


derivation:Extended);
var
i: Integer;
H: Integer;
begin
H := High(Polynom);
FX := Polynom[H];
derivation := 0.0;
for i := H - 1 downto 0 do
begin
derivation := derivation * X + FX;
FX := FX * X + Polynom[i];
end;
end;

{Beispiel / Sample code }

procedure TForm1.Button1Click(Sender: TObject);


var
X, FX, derivation : Extended;
begin
(* Horner's scheme give an algorithm for the simultaneous evaluation
of a given polynomial and its first derivative at a given point *)

(* Hornerschema zur Berechnung eines Polynoms n-ten Grades an einem


bestimmten Punkt *)

(* f(x) = 3 x^5 + 4 x^4 + 13 x^3 - 59 x^2 + 19 x - 97 *)

X := 2.5;
Horner(VarArrayOf([-97,19,-59,13,4,3]),X,FX,derivation);
Showmessage(Format('x = %n'#13#10'f(x) = %n'#13#10'f''(x) = %n',
[X,FX,derivation]));
end;

28
...check if a number is prime ?
Author: Hagen Reddmann

function IsPrime(N: Cardinal): Boolean; register;


// test if N is prime, do some small Strong Pseudo Prime test in certain
bounds
// copyright (c) 2000 Hagen Reddmann, don't remove
asm
TEST EAX,1 // Odd(N) ??
JNZ @@1
CMP EAX,2 // N == 2 ??
SETE AL
RET
@@1: CMP EAX,73 // N < 73 ??
JB @@C
JE @@E // N == 73 ??
PUSH ESI
PUSH EDI
PUSH EBX
PUSH EBP
PUSH EAX // save N as Param for @@5
LEA EBP,[EAX - 1] // M == N -1, Exponent
MOV ECX,32 // calc remaining Bits of M and shift M'
MOV ESI,EBP
@@2: DEC ECX
SHL ESI,1
JNC @@2
PUSH ECX // save Bits as Param for @@5
PUSH ESI // save M' as Param for @@5
CMP EAX,08A8D7Fh // N >= 9080191 ??
JAE @@3
// now if (N < 9080191) and SPP(31, N) and SPP(73, N) then N is prime
MOV EAX,31
CALL @@5 // 31^((N-1)(2^s)) mod N
JC @@4
MOV EAX,73 // 73^((N-1)(2^s)) mod N
PUSH OFFSET @@4
JMP @@5
// now if (N < 4759123141) and SPP(2, N) and SPP(7, N) and SPP(61, N) then N
is prime
@@3: MOV EAX,2
CALL @@5
JC @@4
MOV EAX,7
CALL @@5
JC @@4
MOV EAX,61
CALL @@5
@@4: SETNC AL
ADD ESP,4 * 3
POP EBP
POP EBX
POP EDI
POP ESI
RET
// do a Strong Pseudo Prime Test
@@5: MOV EBX,[ESP + 12] // N on stack
MOV ECX,[ESP + 8] // remaining Bits
MOV ESI,[ESP + 4] // M'
29
MOV EDI,EAX // T = b, temp. Base
@@6: DEC ECX
MUL EAX
DIV EBX
MOV EAX,EDX
SHL ESI,1
JNC @@7
MUL EDI
DIV EBX
AND ESI,ESI
MOV EAX,EDX
@@7: JNZ @@6
CMP EAX,1 // b^((N -1)(2^s)) mod N == 1 mod N ??
JE @@A
@@8: CMP EAX,EBP // b^((N -1)(2^s)) mod N == -1 mod N ?? , EBP = N -1
JE @@A
DEC ECX // second part to 2^s
JNG @@9
MUL EAX
DIV EBX
CMP EDX,1
MOV EAX,EDX
JNE @@8
@@9: STC
@@A: RET
@@B: DB 3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71
@@C: MOV EDX,OFFSET @@B
MOV ECX,18
@@D: CMP AL,[EDX + ECX]
JE @@E
DEC ECX
JNL @@D
@@E: SETE AL
end;

procedure TForm1.Button1Click(Sender: TObject);


begin
if IsPrime(3453451) then
ShowMessage('yes');
end;

30
...fastly retrieve the high-order word from 32bit var ?
Author: Martin
The HiWord function retrieves the high-order word
from the given 32-bit value.

Instead of using HiWord(var32)

use: Word(var32 shr 16)

this is over 60% faster then calling HiWord() function.


Don't make procedure or function out of it (you'll kill the speed).

You could use Word(var32) over LoWord(var32)


but it's less then 1% faster.

********

Die HiWord Funktion extrahiert die das h herwertige Wort (Word) von einem
gegebenen 32-bit Wert.

Anstelle von HiWord(var32)


Verwende: Word((var32 shr 16)

Dies ist ber 60% schneller als die HiWord() Funktion

Man k nnte auch Word((var32) anstatt LoWord((var32) aber dies


ist weniger als 1% schneller.

31
...invert a matrix ?
Author: Kiro Georgiev

type
RCOMat = array of array of Extended;

var
DimMat: integer;

procedure InvertMatrix(var aa: RCOMat);


var
numb, nula1, ipiv, indxr, indxc: array of Integer;
i, j, l, kod, jmax, k, ll, icol, irow: Integer;
amax, d, c, pomos, big, dum, pivinv: Double;
ind: Boolean;
begin
for j := 0 to Pred(DimMat) do ipiv[j] := 0;

irow := 1;
icol := 1;
for i := 0 to Pred(DimMat) do
begin
big := 0;

for j := 0 to Pred(DimMat) do
begin
if (ipiv[j] <> 1) then
begin
for k := 0 to Pred(DimMat) do
begin
if (ipiv[k] = 0) then
if (Abs(aa[j, k]) >= big) then
begin
big := Abs(aa[j, k]);
irow := j;
icol := k;
end else;
end;
end;
end;

ipiv[icol] := ipiv[icol] + 1;
if (irow <> icol) then
begin
for l := 0 to Pred(DimMat) do
begin
dum := aa[irow, l];
aa[irow, l] := aa[icol, l];
aa[icol, l] := dum;
end;
for l := 0 to Pred(DimMat) do
begin
dum := aa[irow + DimMat + 1, l];
aa[irow + DimMat + 1, l] := aa[icol + DimMat + 1, l];
aa[icol + DimMat + 1, l] := dum;
end;
end;
indxr[i] := irow;
indxc[i] := icol;
if (aa[icol, icol] = 0) then;
32
pivinv := 1.0 / aa[icol, icol];
aa[icol, icol] := 1.0;
for l := 0 to Pred(DimMat) do aa[icol, l] := aa[icol, l] * pivinv;
for l := 0 to Pred(DimMat) do aa[icol + DimMat + 1, l] :=
aa[icol + DimMat + 1, l] * pivinv;
for ll := 0 to Pred(DimMat) do
begin
if (ll <> icol) then
begin
dum := aa[ll, icol];
aa[ll, icol] := 0.0;
for l := 0 to Pred(DimMat) do aa[ll, l] := aa[ll, l] aa
[icol, l] * dum;
for l := 0 to Pred(DimMat) do aa[ll + DimMat + 1, l] :=
aa[ll + DimMat + 1, l] - aa[icol + DimMat + 1, l] *
dum;
end;
end;
end;

for l := Pred(DimMat) downto 0 do


begin
if (indxr[l] <> indxc[l]) then
begin
for k := 0 to Pred(DimMat) do
begin
dum := aa[k, indxr[l]];
aa[k, indxr[l]] := aa[k, indxc[l]];
aa[k, indxc[l]] := dum;
end;
end;
end;
end;

33
...calculate the factorial of a given number ?
Author: Los B gu
Homepage: www.begue.de

{
The factorial of a positive integer is defined as:
Die Fakultt einer positiven Nummer ist wie folgt definiert:

n! = n*(n-1)*(n-2)*(n-3)*...*2*1
1! = 1
0! = 1

Example/Beispiel: 5! = 5*4*3*2*1
}

// Iterative Solution, Iterative Lsung:

function FacIterative(n: Word): Longint;


var
f: LongInt;
i: Integer;
begin
f := 1;
for i := 2 to n do f := f * i;
Result := f;
end;

// Recursive Solution, Rekursive Lsung:

function FacRecursive(n: Word): LongInt;


begin
if n > 1 then
Result := n * FacRecursive(n-1)
else
Result := 1;
end;

34
...Draw the Mandelbrot Fractal?
Author: Max Kleiner
Homepage: http://max.kleiner.com

procedure DrawMandelbrot(ACanvas: TCanvas; X, Y, au, bu: Double; X2, Y2:


Integer);
var
c1, c2, z1, z2, tmp: Double;
i, j, Count: Integer;
begin
c2 := bu;
for i := 10 to X2 do
begin
c1 := au;
for j := 0 to Y2 do
begin
z1 := 0;
z2 := 0;
Count := 0;
{count is deep of iteration of the mandelbrot set
if |z| >=2 then z is not a member of a mandelset}
while (((z1 * z1 + z2 * z2 < 4) and (Count <= 90))) do
begin
tmp := z1;
z1 := z1 * z1 - z2 * z2 + c1;
z2 := 2 * tmp * z2 + c2;
Inc(Count);
end;
//the color-palette depends on TColor(n*count mod t)
{$IFDEF LINUX}
ACanvas.Pen.Color := (16 * Count mod 255);
ACanvas.DrawPoint(j, i);
{$ELSE}
ACanvas.Pixels[j, i] := (16 * Count mod 255);
{$ENDIF}
c1 := c1 + X;
end;
c2 := c2 + Y;
end;
end;

35
procedure TForm1.Button1Click(Sender: TObject);
var
R: TRect;
au, ao: Integer;
dX, dY, bo, bu: Double;
begin
// Initialize Mandelbrot
R.Left := 0;
R.Right := 200;
R.Top := 0;
R.Bottom := 205;
ao := 1;
au := -2;
bo := 1.5;
bu := -1.5;
//direct scaling cause of speed
dX := (ao - au) / (R.Right - R.Left);
dY := (bo - bu) / (R.Bottom - R.Top);
DrawMandelbrot(Self.Canvas, dX, dY, au, bu, R.Right, R.Bottom);
end;

36
...convert numbers from one base to another?
Author: Emiliano Alvarez
Homepage: http://www.mainhattan.de.vu/
function BaseConvert(NumIn: string; BaseIn: Byte; BaseOut: Byte): string;
var
i: integer;
currentCharacter: char;
CharacterValue: Integer;
PlaceValue: Integer;
RunningTotal: Double;
Remainder: Double;
BaseOutDouble: Double;
NumInCaps: string;
s: string;
begin
if (NumIn = '') or (BaseIn < 2) or (BaseIn > 36) or (BaseOut < 1) or
(BaseOut > 36) then
begin
Result := 'Error';
Exit;
end;

NumInCaps := UpperCase(NumIn);
PlaceValue := Length(NumInCaps);
RunningTotal := 0;

for i := 1 to Length(NumInCaps) do
begin
PlaceValue := PlaceValue - 1;
CurrentCharacter := NumInCaps[i];
CharacterValue := 0;
if (Ord(CurrentCharacter) > 64) and (Ord(CurrentCharacter) < 91) then
CharacterValue := Ord(CurrentCharacter) - 55;

if CharacterValue = 0 then
if (Ord(CurrentCharacter) < 48) or (Ord(CurrentCharacter) > 57) then
begin
BaseConvert := 'Error';
Exit;
end else
CharacterValue := Ord(CurrentCharacter);

if (CharacterValue < 0) or (CharacterValue > BaseIn - 1) then


begin
BaseConvert := 'Error';
Exit;
end;
RunningTotal := RunningTotal + CharacterValue * (Power(BaseIn,
PlaceValue));
end;

while RunningTotal > 0 do


begin
BaseOutDouble := BaseOut;
Remainder := RunningTotal - (int(RunningTotal / BaseOutDouble) *
BaseOutDouble);
RunningTotal := (RunningTotal - Remainder) / BaseOut;

37
if Remainder >= 10 then
CurrentCharacter := Chr(Trunc(Remainder + 55))
else
begin
s := IntToStr(trunc(remainder));
CurrentCharacter := s[Length(s)];
end;
Result := CurrentCharacter + Result;
end;
end;

// Example, Beispiel

procedure TForm1.Button1Click(Sender: TObject);


begin
BaseConvert('FFFF', 16, 10);
// returns, ergibt '65535'.
end;

38
...determine if a number is prime, quickly (2)?
Author: John A. Stockton
{ *** HTPrimes
**************************************************************

version: 1.1, 13 June 2002


(Version history at end of document.)

author: john.a.stockton@btopenworld.com
Comments, suggestions, bug reports -- all welcome.

purpose: Suite of functions to assist exploring the prime integers to


High(Cardinal), ie. up to 4,294,967,295. Includes an
efficient
primality test combining factorisation and SPRP approaches,
implemented (almost) entirely in Pascal.

licence: Free for non-commercial use.


A postcard would be very much appreciated from commercial
users (royalty cheques also gratefully received - if your
conscience gets the better of you).

***************************************************************************

NOTE: The StrongProbablePrime and WeakProbablePrime functions depend on an


ancillary function, MulMod. MulMod is a kludge that uses an
assembler
shortcut. It might not work on all compilers. It has been tested on
Delphi 5 (dcc32 v13.0) and Delphi 6 (dcc32 v14.0).

The current implementation of MulMod is also prone to trigger #DE


exceptions (expressed as EIntOverflow by Delphi), for large values
of
B in calls to StrongProbablePrime and WeakProbablePrime. A slower,
but
safe version of the function is included in a comment.

***************************************************************************
}

unit HTPrimes;

interface { *************************************************** Interface


*** }

const
MaxPrime = High(Cardinal) - 4;
{ The highest prime in the range of the Cardinal type.
P(203,280,221) = 4,294,967,291. }

type
TPrimeFactor = record
p, q: Cardinal;
end;

TPrimeFactorArray = array of TPrimeFactor;

39
{ Record and dynamic array types used by the GetPrimeFactors function
(see below). }

TPrimeArray = array of Cardinal;


{ Dynamic array type used by the GetGoldbachPairs function (see
below). }

{ ************************************************* Function Declarations


*** }

function IsPrime(Nmbr: Cardinal): Boolean;


{ True if Nmbr is prime, False otherwise. }

function StrongProbablePrime(N, B: Cardinal): Boolean;


{ True if N is a strong probable prime (SPRP) base B. False if N is
composite, or if either N or B < 2.

SPRP base B - Write:


N - 1 = 2^s * d, with s >= 0 and d odd,
then N is probably prime if either:
B^d = 1 (mod N), or
(B^d)^(2^r) = -1 (mod N), for 0 <= r < s. }

function WeakProbablePrime(N, B: Cardinal): Boolean;


{ True if N is a probable prime (PRP) base N. False if N is composite,
or if either N or B < 2.

PRP base B - If B^(N-1) = 1 (mod N), then N is probably prime. }

function Pseudoprime(N, B: Cardinal): Boolean;


{ True if N is a PRP base B, but composite. }

function StrongPseudoprime(N, B: Cardinal): Boolean;


{ True if N is a SPRP base B, but composite. }

function IsComposite(Nmbr: Cardinal): Boolean;


{ True if Nmbr is composite. This isn't equivalent to not IsPrime(Nmbr),
because 0 and 1 are neither prime nor composite. }

function NextPrime(Nmbr: Cardinal): Cardinal;


{ Returns the first prime greater than Nmbr, or 0 if the search exceeds
MaxPrime. }

function PreviousPrime(Nmbr: Cardinal): Cardinal;


{ Returns the greatest prime less than Nmbr, or 0 if no such prime
exists. }

function RandomPrime(Range: Cardinal): Cardinal;


{ Returns a random prime, X, such that 2 <= X < Range for Range > 2.
As with the system function Random, initialise the random number
generator
by calling Randomize, or assigning a value to RandSeed.

Returns 0 for Range <= 2. }

function IsJuniorTwin(Nmbr: Cardinal): Boolean;


{ True if Nmbr and Nmbr + 2 are both prime, ie. if they form a 'twin
pair'.
False if either are composite, or if Nmbr >= MaxPrime. }

40
function IsSeniorTwin(Nmbr: Cardinal): Boolean;
{ True if Nmbr and Nmbr - 2 form a twin pair. }

function GapToNextPrime(Nmbr: Cardinal): Cardinal;


{ Returns the gap to the next prime, where Gap = NextPrime - Nmbr.
Returns 0 if the next prime exceeds MaxPrime. }

function CountPrimesInRange(P, Q: Cardinal): Cardinal;


{ Returns the count of primes, X, that satisfy P <= X <= Q. }

function RangeContainsPrime(P, Q: Cardinal): Boolean;


{ True if there is at least one prime, X, that satisfies P <= X <= Q.
Equivalent to CountPrimesInRange(P, Q) > 0, but faster. }

function IsPrimeFactor(Nmbr, Fctr: Cardinal): Boolean;


{ True if Fctr is prime, and a factor of Nmbr. }

function GetPrimeFactors(Nmbr: Cardinal; var Fctrs: TPrimeFactorArray):


Boolean;
{ True if Nmbr is greater than one. Fctrs will contain Nmbr's prime
factors
in TPrime records such that p = the factor, q = exponent that p is
raised
to in factorization of Nmbr. It is not necessary to initialise the array
referenced by Fctrs, it will be dynamically sized as required.

False if Nmbr is less than two. }

function CountPrimeFactors(Nmbr: Cardinal): Word;


{ Equivalent to summing exponents after a call to GetPrimeFactors.
However,
this function does not require memory for storing the factors and is
faster
if you only need to know how many factors there are. }

function CountUniqueFactors(Nmbr: Cardinal): Word;


{ Equivalent to Length(Fctrs) after a call to GetPrimeFactors, but
faster. }

function LeastPrimeFactor(Nmbr: Cardinal): Cardinal;


{ Returns the smallest prime factor of Nmbr. 0 if Nmbr is less than 2.
If you're only interested in the least prime factor of Nmbr, this
function
is faster than calling GetPrimeFactors and then examining Fctrs[0]. }

function GreatestPrimeFactor(Nmbr: Cardinal): Cardinal;


{ Returns the greatest prime factor of Nmbr. 0 if Nmbr is less than 2.
As with LeastPrimeFactors, this function is faster than calling
GetPrimeFactors and then examining Fctrs[High(Fctrs)]. }

function GreatestCommonDivisor(P, Q: Cardinal): Cardinal; overload;


{ Returns the greatest common divisor of P and Q, ie. the largest integer
that divides them both. }

function GreatestCommonDivisor(Nmbrs: array of Cardinal): Cardinal;


overload;
{ Returns the greatest common divisor of the elements of Nmbrs, ie. the
largest integer that divides them all.

Returns 0 if Nmbrs has less than two elements. }


41
function LeastCommonMultiple(P, Q: Cardinal): Int64; overload;
{ Returns the lowest positive integer that both P and Q divide. Returns 0
if
either P or Q are 0. }

function LeastCommonMultiple(Nmbrs: array of Cardinal): Int64; overload;


{ Returns the lowest positive integer that can be divided by all elements
of
Nmbrs. Returns 0 if any element of Nmbrs is 0, or if Nmbrs has less than
2 elements.

Note: The LCM of even a small collection of integers can be surprisingly


large, and neither version of this function makes any effort to
deal
with overflows beyond High(Int64). Use with caution. }

function AreRelativelyPrime(P, Q: Cardinal): Boolean;


{ True if P and Q are relatively prime, ie. their greatest common divisor
is
one. }

function AreMutuallyPrime(Nmbrs: array of Cardinal): Boolean;


{ True if the elements of Nmbrs are mutually relatively prime, ie. if
there
is no integer that divides them all (other than one).

False if Nmbrs are not mutually relatively prime, or if Nmbrs has less
than
two elements. }

function ArePairwisePrime(Nmbrs: array of Cardinal): Boolean;


{ True if the elements of Nmbrs are pairwise relatively prime, ie. if
every
unique pairing of elements in Nmbrs is relatively prime.

False if Nmbrs are not pairwise relatively prime, or if Nmbrs has less
than
two elements. }

function GetGoldbachPairs(Nmbr: Cardinal; var Primes: TPrimeArray): Boolean;


{ True if Nmbr is even and greater than 2. The Primes array will be
populated
with the low members of all prime pairs that satisfy P1 + P2 = Nmbr.

False if Nmbr is odd or 2. The length of Pairs will be 0. }

function CountGoldbachPairs(Nmbr: Cardinal): Cardinal;


{ If Nmbr is even and greater than 2, returns the number of prime pairs
that
satisfy P1 + P2 = Nmbr. Equivalent to Length(Primes) after a call to
GetGoldbachPairs, but faster and without the memory overhead.

0 if Nmbr is odd or 2 (or if Nmbr refutes Goldbach's Conjecture). }

function IsGoldbachPair(P, Q: Cardinal): Boolean;


{ True if both P and Q are prime, and P + Q is even and greater than 2. }

function HasGoldbachPair(Nmbr: Cardinal): Boolean;


{ True if Nmbr is even, greater than two and is the sum of two primes, in
42
at
least one way. Equivalent to CountGoldbachPairs(Nmbr) > 0, but much
faster. }

implementation { ***************************************** implementation


*** }

uses Math;

{$B-}

{ ****************************************************** function IsPrime


*** }
function IsPrime(Nmbr: Cardinal): Boolean;
const
PF: array[0..8] of Cardinal = (2, 3, 5, 7, 11, 13, 17, 19, 23);
var
i: Cardinal;
begin
case Nmbr of
0..1: IsPrime := False;
{ 0 and 1 are neither prime nor composite. }
2, 7, 61: IsPrime := True;
{ These three rogues break the test, so deal with them here. }
else
begin
{ Do a quick factorisation test using the primes in PF. The list is so
short that restricting the factor search to values <= Sqrt(Nmbr) is
counter-productive, because of the overhead of calculating the square
root. If you extend the factor list, try changing the last inequality
in the repeat...until test to (PF[i] > Trunc(Sqrt(Nmbr))). }
i := 0;
repeat
Result := ((Nmbr mod PF[i]) > 0);
Inc(i);
until (not Result) or (i > High(PF)) or (PF[i] >= Nmbr);

{ If Result is still True, hammer Nmbr with some SPRP tests.


If Nmbr < 4,759,123,141 and is a 2, 7 and 61 SPRP, then Nmbr is
prime. }
Result := Result and
StrongProbablePrime(Nmbr, 2) and
StrongProbablePrime(Nmbr, 7) and
StrongProbablePrime(Nmbr, 61);
end;
end;
end; { function IsPrime }

{ ****************************** function MulMod (fast but risky version)


*** }
function MulMod(x, y, m: Cardinal): Cardinal;
{ Assumes that on entry: eax = x, edx = y and ecx = m. Self destructs with
a
#DE (divide error) exception when x and y are large. }
asm
mul edx
div ecx
mov eax, edx
end; { function MulMod }

43
{ ******************************* function MulMod (safe but slow version)
***
function MulMod(x, y, m: Cardinal): Cardinal;
var
i, j: Cardinal;
begin
i := x mod m;
j := y mod m;
asm
mov eax, i
mul j
div m
mov i, edx
end;
MulMod := i;
end; }

{ ****************************************** function StrongProbablePrime


*** }
function StrongProbablePrime(N, B: Cardinal): Boolean;
var
d, i, r, s: Cardinal;
begin
if (Min(N, B) < 2) then
StrongProbablePrime := False
else
begin
{ Find d and s that satisfy N - 1 = 2^s * d, where d is odd and s >= 0. }
d := N - 1;
s := 0;
while ((d and 1) = 0) do
begin
d := d shr 1;
Inc(s);
end;

{ Use right-to-left binary exponentiation to Calculate B^d mod N,


result in i. }
i := 1;
r := B;
while (d > 1) do
begin
if ((d and 1) = 1) then
i := MulMod(i, r, N);
d := d shr 1;
r := MulMod(r, r, N);
end;
i := MulMod(i, r, N);

{ If i = 1 or N - 1, then N is a SPRP base B. }


Result := (i = 1) or (i = N - 1);

{ Otherwise, see if i^(2^r) mod N = N - 1, where 0 <= r < s. }


r := 0;

while ((not Result) and (r + 1 <= s)) do


begin
i := MulMod(i, i, N);

44
Result := (i = N - 1);
Inc(r);
end;
end;
end; { function StrongProbablePrime }

{ ******************************************** function WeakProbablePrime


*** }

function WeakProbablePrime(N, B: Cardinal): Boolean;


var
d, i, r: Cardinal;
begin
if (Min(N, B) < 2) then
WeakProbablePrime := False
else
begin
{ Use right-to-left binary exponentiation to calculate B^(N-1) mod N,
result in i. }
d := N - 1;
i := 1;
r := B;
while (d > 1) do
begin
if ((d and 1) = 1) then
i := MulMod(i, r, N);
d := d shr 1;
r := MulMod(r, r, N);
end;
i := MulMod(i, r, N);

WeakProbablePrime := (i = 1);
end;
end; { function WeakProbablePrime }

{ ************************************************** function PseudoPrime


*** }
function Pseudoprime(N, B: Cardinal): Boolean;
begin
Pseudoprime := WeakProbablePrime(N, B) and IsComposite(N);
end; { function Pseudoprime }

{ ******************************************** function StrongPseudoPrime


*** }
function StrongPseudoprime(N, B: Cardinal): Boolean;
begin
StrongPseudoPrime := StrongProbablePrime(N, B) and IsComposite(N);
end; { function StrongPseudoprime }

{ ************************************************** function IsComposite


*** }
function IsComposite(Nmbr: Cardinal): Boolean;

45
begin
{ Not quite as trivial as negating IsPrime(Nmbr), but almost. }
IsComposite := (Nmbr > 3) and (not IsPrime(Nmbr));
end; { function IsComposite }

{ **************************************************** function NextPrime


*** }
function NextPrime(Nmbr: Cardinal): Cardinal;
begin
if (Nmbr >= MaxPrime) then
{ Return 0 as an error result if Nmbr >= MaxPrime. }
NextPrime := 0
else
begin
{ Deal with Nmbr < 2 separately, because the main search only considers
odd candidates and will therefore miss 2. }
if (Nmbr < 2) then
NextPrime := 2
else
begin
{ Set Result to the next odd number. }
Result := Nmbr + 1;
if ((Result and 1) = 0) then
Inc(Result);

{ Then test consecutive odd numbers until we find a prime. }


while (not IsPrime(Result)) do
Inc(Result, 2);
end;
end;
end; { function NextPrime }

{ ************************************************ function PreviousPrime


*** }
function PreviousPrime(Nmbr: Cardinal): Cardinal;
begin
case Nmbr of
{ 0, 1 and 2 have no previous prime, so return 0 as an error result. }
0..2: PreviousPrime := 0;
{ As in NextPrime, the main search only considers odd candidates so
Start = 3 is a special case and has to be dealt with separately. }
3: PreviousPrime := 2;
else
begin
{ Set Result to the greatest preceding odd number. }
Result := Nmbr - 1;
if ((Result and 1) = 0) then
Dec(Result);

{ Then test consecutive odd numbers (counting down) until we discover a


prime. }
while (not IsPrime(Result)) do
Dec(Result, 2);
end;
end;
end; { function PreviousPrime }

{ ************************************************** function RandomPrime


*** }
function RandomPrime(Range: Cardinal): Cardinal;
46
begin
if (Range <= 2) then
RandomPrime := 0
else
repeat
Result := NextPrime(Random(Range - 1));
until (Result > 0) and (Result < Range);
end; { function RandomPrime }

{ ************************************************* function IsJuniorTwin


*** }
function IsJuniorTwin(Nmbr: Cardinal): Boolean;
begin
Result := (Nmbr < MaxPrime);
if Result then
Result := IsPrime(Nmbr) and IsPrime(Nmbr + 2);
end; { function IsJuniorTwin }

{ ************************************************* function IsSeniorTwin


*** }
function IsSeniorTwin(Nmbr: Cardinal): Boolean;
begin
Result := (Nmbr > 2);
if Result then
Result := IsPrime(Nmbr) and IsPrime(Nmbr - 2);
end; { function IsSeniorTwin }

{ *********************************************** function GapToNextPrime


*** }
function GapToNextPrime(Nmbr: Cardinal): Cardinal;
begin
Result := NextPrime(Nmbr);
if (Result > 0) then
Result := Result - Nmbr;
end; { function GapToNextPrime }

{ ******************************************* function CountPrimesInRange


*** }
function CountPrimesInRange(P, Q: Cardinal): Cardinal;
begin
Result := 0;
if (P <= Q) then
begin
if (P > 0) then
Dec(P);
while (P <= Q) do
begin
P := NextPrime(P);
Inc(Result);
end;
Dec(Result);
end;
end; { function CountPrimesInRange }

{ ******************************************* function RangeContainsPrime


*** }
function RangeContainsPrime(P, Q: Cardinal): Boolean;
begin
RangeContainsPrime := False;
if ((P <= Q) and (P < MaxPrime)) then
47
begin
if (P > 0) then
Dec(P);
Result := (NextPrime(P) <= Q);
end;
end; { function RangeContainsPrime }

{ ************************************************ function IsPrimeFactor


*** }
function IsPrimeFactor(Nmbr, Fctr: Cardinal): Boolean;
begin
IsPrimeFactor := ((Nmbr mod Fctr) = 0) and IsPrime(Fctr);
end; { function IsPrimeFactor }

{ ********************************************** function GetPrimeFactors


*** }
function GetPrimeFactors(Nmbr: Cardinal; var Fctrs: TPrimeFactorArray):
Boolean;
var
i, k: Cardinal;
begin
SetLength(Fctrs, 0);
Result := (Nmbr > 1);
if Result then
begin
k := 0;
repeat
{ If Nmbr is prime at this stage, it must be the original Nmbr's greatest
prime factor. If Nmbr isn't prime, search for a prime that divides it,
starting from two. }
if IsPrime(Nmbr) then
i := Nmbr
else
begin
i := 2;
while ((Nmbr mod i) > 0) do
i := NextPrime(i);
end;

{ Store the found factor. Append it to Fctrs if it's not already known,
otherwise increment the exponent. }
if (i > k) then
begin
k := i;
SetLength(Fctrs, Length(Fctrs) + 1);
Fctrs[High(Fctrs)].p := i;
Fctrs[High(Fctrs)].q := 1;
end else
Inc(Fctrs[High(Fctrs)].q);

{ Divide Nmbr by the last factor found. If this doesn't reduce Nmbr to
one then go back to find the lowest prime factor of the new value. }
Nmbr := Nmbr div i;
until (Nmbr = 1);
end;
end; { function GetPrimeFactors }

{ ******************************************** function CountPrimeFactors


*** }
function CountPrimeFactors(Nmbr: Cardinal): Word;
48
var
i: Cardinal;
begin
Result := 0;
while (Nmbr > 1) do
begin
if IsPrime(Nmbr) then
i := Nmbr
else
begin
i := 2;
while ((Nmbr mod i) > 0) do
i := NextPrime(i);
end;
Inc(Result);
Nmbr := Nmbr div i;
end;
end; { function CountPrimeFactors }

{ ******************************************* function CountUniqueFactors


*** }
function CountUniqueFactors(Nmbr: Cardinal): Word;
var
i, j: Cardinal;
begin
Result := 0;
j := 0;
while (Nmbr > 1) do
begin
if IsPrime(Nmbr) then
begin
if (Nmbr <> j) then
Inc(Result);
i := Nmbr;
end else
begin
i := 2;
while ((Nmbr mod i) > 0) do
i := NextPrime(i);
if (i > j) then
begin
j := i;
Inc(Result);
end;
end;
Nmbr := Nmbr div i;
end;
end; { function CountUniqueFactors }

{ ********************************************* function LeastPrimeFactor


*** }
function LeastPrimeFactor(Nmbr: Cardinal): Cardinal;
begin
if (Nmbr < 2) then
LeastPrimeFactor := 0

49
else if IsPrime(Nmbr) then
Result := Nmbr
else
begin
Result := 2;
while ((Nmbr mod Result) > 0) do
Result := NextPrime(Result);
end;
end; { function LeastPrimeFactor }

{ ****************************************** function GreatestPrimeFactor


*** }
function GreatestPrimeFactor(Nmbr: Cardinal): Cardinal;
begin
if (Nmbr < 2) then
GreatestPrimeFactor := 0
else
begin
Result := Nmbr;
while (not IsPrime(Result)) do
Result := Result div LeastPrimeFactor(Result);
end;
end; { function GreatestPrimeFactor }

{ **************************************** function GreatestCommonDivisor


*** }
function GreatestCommonDivisor(P, Q: Cardinal): Cardinal;
var
i: Cardinal;
begin
Result := 0;
if (Min(P, Q) > 0) then
begin
{ Use the Euclidean Algorithm to find the GCD of P and Q. Much faster
than
calculating the product of the prime factors that they have in common,
but much less interesting. }
while (Q > 0) do
begin
i := P mod Q;
P := Q;
Q := i;
end;
Result := P;
end;
end; { function GreatestCommonDivisor(P, Q: Cardinal) }

function GreatestCommonDivisor(Nmbrs: array of Cardinal): Cardinal;


var
i, j: Cardinal;
begin
if (Length(Nmbrs) < 2) then

50
Result := 0
else
begin
j := Low(Nmbrs);
Result := GreatestCommonDivisor(Nmbrs[j], Nmbrs[j + 1]);
for i := j + 2 to High(Nmbrs) do
Result := GreatestCommonDivisor(Result, Nmbrs[i]);
end;
end; { function GreatestCommonDivisor(Nmbrs: array of Cardinal) }

{ ****************************************** function LeastCommonMultiple


*** }
function LeastCommonMultiple(P, Q: Cardinal): Int64;
begin
Result := GreatestCommonDivisor(P, Q);
if (Result > 0) then
begin
{ LCM(a, b) = ab/GCD(a, b) }
P := P div Result;
LeastCommonMultiple := Int64(P) * Int64(Q);
end;
end; { function LeastCommonMultiple(P, Q: Cardinal) }

function LeastCommonMultiple(Nmbrs: array of Cardinal): Int64;


var
i, j: Cardinal;
begin
Result := 0;
if (Length(Nmbrs) > 1) then
begin
j := Low(Nmbrs);
Result := LeastCommonMultiple(Nmbrs[j], Nmbrs[j + 1]);
for i := j + 2 to High(Nmbrs) do
Result := LeastCommonMultiple(Result, Nmbrs[i]);
end;
end; { LeastCommonMultiple(Nmbrs: array of Cardinal) }

{ ******************************************* function AreRelativelyPrime


*** }
function AreRelativelyPrime(P, Q: Cardinal): Boolean;
begin
AreRelativelyPrime := (GreatestCommonDivisor(P, Q) = 1);
end; { function AreRelativelyPrime }

{ ********************************************* function AreMutuallyPrime


*** }
function AreMutuallyPrime(Nmbrs: array of Cardinal): Boolean;
begin
AreMutuallyPrime := (GreatestCommonDivisor(Nmbrs) = 1)
end; { function AreMutuallyPrime }

{ ********************************************* function ArePairwisePrime


*** }
function ArePairwisePrime(Nmbrs: array of Cardinal): Boolean;
var
i, j: Cardinal;
begin

51
Result := (Length(Nmbrs) > 1);
if Result then
begin
i := Low(Nmbrs);
while (Result and (i <= High(Nmbrs))) do
begin
j := i + 1;
while (Result and (j <= High(Nmbrs))) do
begin
Result := (Result and AreRelativelyPrime(Nmbrs[i], Nmbrs[j]));
Inc(j);
end;
Inc(i);
end;
end;
end; { function ArePairwisePrime }

{ ********************************************* function GetGoldbachPairs


*** }
function GetGoldbachPairs(Nmbr: Cardinal; var Primes: TPrimeArray): Boolean;
var
i: Cardinal;
begin
SetLength(Primes, 0);
Result := (Nmbr > 2) and ((Nmbr and 1) = 0);
if Result then
begin
{ Starting from 2, subtract consecutive primes from Nmbr and check if the
result is prime. Stop when Nmbr div 2 is exceeded, because then we're
just discovering the reversed versions of the pairs we have already. }
i := 2;
while (i <= (Nmbr div 2)) do
begin
if IsPrime(Nmbr - i) then
begin
SetLength(Primes, Length(Primes) + 1);
Primes[High(Primes)] := i;
end;
i := NextPrime(i);
end;
end;
end; { function GetGoldbachPairs }

{ ******************************************* function CountGoldbachPairs


*** }
function CountGoldbachPairs(Nmbr: Cardinal): Cardinal;
var
i: Cardinal;
begin

52
Result := 0;
if ((Nmbr > 2) and ((Nmbr and 1) = 0)) then
begin
i := 2;
while (i <= (Nmbr div 2)) do
begin
if IsPrime(Nmbr - i) then
Inc(Result);
i := NextPrime(i);
end;
end;
end; { function CountGoldbachPairs }

{ ********************************************** function HasGoldbachPair


*** }
function HasGoldbachPair(Nmbr: Cardinal): Boolean;
var
i: Cardinal;
begin
Result := ((Nmbr > 2) and ((Nmbr and 1) = 0));
if Result then
begin
i := 2;
Result := False;
while (not Result and (i <= (Nmbr div 2))) do
if IsPrime(Nmbr - i) then
Result := True
else
i := NextPrime(i);
end;
end; { function HasGoldbachPair }

{ *********************************************** function IsGoldbachPair


*** }
function IsGoldbachPair(P, Q: Cardinal): Boolean;
begin
IsGoldbachPair := (((P + Q) and 1) = 0) and (P + Q > 2) and
IsPrime(P) and IsPrime(Q);
end; { function IsGoldbachPair }

{ ******************************************************* Version History


***

To
do ---------------------------------------------------------------------

Any suggestions?

v1.1, 13 June
2002 --------------------------------------------------------

Additions:
function WeakProbablePrime
function PseudoPrime
function StrongPseudoprime
function RandomPrime

Changes:
01 Moved IsPrime's declaration to make it more obvious.
02 MulMod: Promoted so WeakProbablePrime can use it.
53
03 Mulmod: 'Safe' version re-written to permit SPRP and PRP with large
bases.
04 IsPrime: Shortened the prime factor list. The shorter list seems to
be more efficient in combination with the SPRP tests.
05 IsPrime: Scrapped the restriction that (trial factor) <= Sqrt(Nmbr).
With the short prime factor list, calculating Trunc(Sqrt(Nmbr))
is an unwarranted overhead. Also replaced the while loop with a
repeat until loop, because it looks neater and doesn't damage
performance.

v1.0, 12 June
2002 --------------------------------------------------------

Original release. }

end. { ********************************************************** THE END


*** }

54
...use Base64 encoding and decoding?
Author: Steve Schafer
Homepage: http://www.teamb.com
function Decode(const S: AnsiString): AnsiString;
const
Map: array[Char] of Byte = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0);
var
I: LongInt;
begin
case Length(S) of
2: begin
I := Map[S[1]] + (Map[S[2]] shl 6);
SetLength(Result, 1);
Move(I, Result[1], Length(Result))
end;
3: begin
I := Map[S[1]] + (Map[S[2]] shl 6) + (Map[S[3]] shl 12);
SetLength(Result, 2);
Move(I, Result[1], Length(Result))
end;
4: begin
I := Map[S[1]] + (Map[S[2]] shl 6) + (Map[S[3]] shl 12) +
(Map[S[4]] shl 18);
SetLength(Result, 3);
Move(I, Result[1], Length(Result))
end;
end;
end;

55
function Encode(const S: AnsiString): AnsiString;
const
Map: array[0..63] of Char = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
'abcdefghijklmnopqrstuvwxyz0123456789+/';
var
I: LongInt;
begin
I := 0;
Move(S[1], I, Length(S));
case Length(S) of
1: Result := Map[I mod 64] + Map[(I shr 6) mod 64];
2: Result := Map[I mod 64] + Map[(I shr 6) mod 64] +
Map[(I shr 12) mod 64];
3: Result := Map[I mod 64] + Map[(I shr 6) mod 64] +
Map[(I shr 12) mod 64] + Map[(I shr 18) mod 64]
end
end;

56
...Calculate Easter Day for a specified year?
Author: Mark Lussier
function Easter(Year: Integer): TDateTime;
{----------------------------------------------------------------}
{ Calculates and returns Easter Day for specified year. }
{ Originally from Mark Lussier, AppVision <MLussier@best.com>. }
{ Corrected to prevent integer overflow if it is inadvertently }
{ passed a year of 6554 or greater. }
{----------------------------------------------------------------}
var
nMonth, nDay, nMoon, nEpact, nSunday, nGold, nCent, nCorx, nCorz: Integer;
begin
{ The Golden Number of the year in the 19 year Metonic Cycle: }
nGold := (Year mod 19) + 1;
{ Calculate the Century: }
nCent := (Year div 100) + 1;
{ Number of years in which leap year was dropped in order... }
{ to keep in step with the sun: }
nCorx := (3 * nCent) div 4 - 12;
{ Special correction to syncronize Easter with moon's orbit: }
nCorz := (8 * nCent + 5) div 25 - 5;
{ Find Sunday: }
nSunday := (Longint(5) * Year) div 4 - nCorx - 10;
{ ^ To prevent overflow at year 6554}
{ Set Epact - specifies occurrence of full moon: }
nEpact := (11 * nGold + 20 + nCorz - nCorx) mod 30;
if nEpact < 0 then
nEpact := nEpact + 30;
if ((nEpact = 25) and (nGold > 11)) or (nEpact = 24) then
nEpact := nEpact + 1;
{ Find Full Moon: }
nMoon := 44 - nEpact;
if nMoon < 21 then
nMoon := nMoon + 30;
{ Advance to Sunday: }
nMoon := nMoon + 7 - ((nSunday + nMoon) mod 7);
if nMoon > 31 then
begin
nMonth := 4;
nDay := nMoon - 31;
end else
begin
nMonth := 3;
nDay := nMoon;
end;
Easter := EncodeDate(Year, nMonth, nDay);
end; {Easter}

57
...calculate the german holidays?
Author: Benny Baumann
unit Feiertage;
// Unit Holidays;

interface

uses
Windows, SysUtils;

// Declare a structure to hold the Information


// Deklarieren der Struktur, um die Feiertage abzuspeichern
type
THoliday = record
Date: TDateTime;
Name: string;
end;
THolidayTable = array of THoliday;

// Function to call to get the Holiday Table with all Holidays of a year
// Der Funktionsaufruf, um die Feiertage eines Jahres abzufragen
function GetHolidayTable(Year: Word): THolidayTable;

implementation

function TUrlaubsForm.GetHolidayTable(Year: Word): THolidayTable;

// Function to add a holiday by Day and Month


// Funktion, um einen Feiertag ber seinen Tag\Monat hinzuzufgen
procedure AddHoliday(DD, MM: Word; HDName: string); overload;
begin
SetLength(Result, High(Result) + 2);
with Result[High(Result)] do
begin
Date := EncodeDate(Year, MM, DD);
Name := HDName;
end;
end;

//Function to add holiday by date serial


//Funktion, um den Feiertag ber die Datumsseriennummer hinzuzufgen
procedure AddHoliday(HDDate: TDateTime; HDName: string); overload;
begin
SetLength(Result, High(Result) + 2);
with Result[High(Result)] do
begin
Date := HDDate;
Name := HDName;
end;
end;

58
// Function to get easter sunday
// Function zur Berechnung des Ostersonntags
function GetEasterDate(YYYY: Word): TDateTime;
var
A, B, C, D, E, F, G, H, I, K, L, M, N, P: Word;
DD, MM: Word;
begin
a := YYYY mod 19;
b := YYYY div 100;
c := YYYY mod 100;
d := b div 4;
e := b mod 4;
f := (b + 8) div 25;
g := (b - f + 1) div 3;
h := (19 * a + b - d - g + 15) mod 30;
i := c div 4;
k := c mod 4;
l := (32 + 2 * e + 2 * i - h - k) mod 7;
m := (a + 11 * h + 22 * l) div 451;
n := (h + l - 7 * m + 114) div 31;
p := (h + l - 7 * m + 114) mod 31 + 1;
DD := p;
MM := n;
Result := EncodeDate(YYYY, MM, DD);
end;

var
EDate: TDateTime;
begin
// Add fixed holidays
// Hinzufgen der festen Feiertage
AddHoliday(1, 1, 'Neujahr');
AddHoliday(1, 5, 'Tag der Arbeit');
AddHoliday(3, 10, 'Tag der deutschen Einheit');
AddHoliday(31, 10, 'Reformationstag');
// AddHoliday(24, 12, 'Heiligabend');
AddHoliday(25, 12, '1. Weihnachtsfeiertag');
AddHoliday(26, 12, '2. Weihnachtsfeiertag');
// AddHoliday(31, 12, 'Silvester');
// Add holidays relative to easter sunday
// Hinzufgen der Feiertage, die von Ostern abhngen
EDate := GetEasterDate(Year);
AddHoliday(EDate, 'Ostersonntag');
AddHoliday(EDate - 2, 'Karfreitag');
AddHoliday(EDate + 1, 'Ostermontag');
AddHoliday(EDate + 39, 'Christi Himmelfahrt');
AddHoliday(EDate + 49, 'Pfingstsonntag');
AddHoliday(EDate + 50, 'Pfingstmontag');
// Gets 3rd Wednesday in November
// Ermittelt den 3. Mitwoch im November
EDate := EncodeDate(Year, 11, 1);
EDate := EDate + ((11 - DayOfWeek(EDate)) mod 7) + 14;
AddHoliday(EDate, 'Bu- und Bettag');
end;

end.

// This Units works since the year 1584


// Diese Unit arbeitet mit Jahreszahlen nach 1584
59
60
...multiply big integer values?
Author: Mileriam
Homepage: http://www.mediaceta.de
type
IntNo = record
Low32, Hi32: DWORD;
end;

function Multiply(p, q: DWORD): ntNo;


var
x: ntNo;
begin
asm
MOV EAX,[p]
MUL [q]
MOV [x.Low32],EAX
MOV [x.Hi32],EDX
end;
Result := x
end;

// Test the above with:


// So kannst du es testen

var
r: IntNo;
begin
r := Multiply(40000000, 80000000);
ShowMessage(IntToStr(r.Hi32) + ', ' + IntToStr(r.low32))
end;

61
...calculate the logarithm for a variable base?
Author: Alexander Schimpf
Homepage: http://www.hitstec.de
(*

--- English ------


A logarithm function with a variable basis

--- Deutsch ------


In Delphi ist die Funktion LN() bekannt, die den
natrlichen Logarithmus einer Zahl zurckgibt.
Der natrliche Logarithmus hat die Basis e^1.

Um den Logarithmus zur varaiblen Basis zu berechnen


hilft folgende Funktion.

*)

function Log(x, b: Real): Real;


begin
Result := ln(x) / ln(b);
end;

procedure TForm1.Button1Click(Sender: TObject);


begin
ShowMessage(Format('%f', [Log(10, 10)]));
end;

62
...validate an IBAN?
Author: Katja Hoffmann
Homepage: http://www.katjahoffmann.gmxhome.de
// IBAN = International Bank Account Number
// Example : CH10002300A1023502601

function ChangeAlpha(input: string): string;


// A -> 10, B -> 11, C -> 12 ...
var
a: Char;
begin
Result := input;
for a := 'A' to 'Z' do
begin
Result := StringReplace(Result, a, IntToStr(Ord(a) - 55),
[rfReplaceAll]);
end;
end;

function CalculateDigits(iban: string): Integer;


var
v, l: Integer;
alpha: string;
number: Longint;
rest: Integer;
begin
iban := UpperCase(iban);
if Pos('IBAN', iban) > 0 then
Delete(iban, Pos('IBAN', iban), 4);
iban := iban + Copy(iban, 1, 4);
Delete(iban, 1, 4);
iban := ChangeAlpha(iban);
v := 1;
l := 9;
rest := 0;
alpha := '';
try
while v <= Length(iban) do
begin
if l > Length(iban) then
l := Length(iban);
alpha := alpha + Copy(iban, v, l);
number := StrToInt(alpha);
rest := number mod 97;
v := v + l;
alpha := IntToStr(rest);
l := 9 - Length(alpha);
end;
except
rest := 0;
end;
Result := rest;
end;

function CheckIBAN(iban: string): Boolean;

63
begin
iban := StringReplace(iban, ' ', '', [rfReplaceAll]);
if CalculateDigits(iban) = 1 then
Result := True
else
Result := False;
end;

64
...calculate the age of a person?
Author: Simon Grossenbacher
Homepage: http://www.swissdelphicenter.ch

function CalculateAge(Birthday, CurrentDate: TDate): Integer;


var
Month, Day, Year, CurrentYear, CurrentMonth, CurrentDay: Word;
begin
DecodeDate(Birthday, Year, Month, Day);
DecodeDate(CurrentDate, CurrentYear, CurrentMonth, CurrentDay);

if (Year = CurrentYear) and (Month = CurrentMonth) and

(Day = CurrentDay) then


begin
Result := 0;
end else
begin
Result := CurrentYear - Year;
if (Month > CurrentMonth) then
Dec(Result)
else
begin
if Month = CurrentMonth then
if (Day > CurrentDay) then
Dec(Result);
end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);


begin
Label1.Caption := Format('Your age is %d', [CalculateAge(StrToDate('01.01.1
903'), Date)]);
end;

65
...sort an Array with the Shell Sort Algorithm?
Author: Stormer

{
The following procedure sorts an Array with the
fast Shell-Sort algorithm.
Invented by Donald Shell in 1959,
the shell sort is the most efficient of the O(n2)
class of sorting algorithms
}

{
Die folgende Prozedur Sortiert ein Array mit
dem schnellem Shell-Sort Algorithmus.
}

Procedure Sort_Shell(var a: array of Word);


var
bis, i, j, k: LongInt;
h: Word;
begin
bis := High(a);
k := bis shr 1;// div 2
while k > 0 do
begin
for i := 0 to bis - k do
begin
j := i;
while (j >= 0) and (a[j] > a[j + k]) do
begin
h := a[j];
a[j] := a[j + k];
a[j + k] := h;
if j > k then
Dec(j, k)
else
j := 0;
end; // {end while]
end; // { end for}
k := k shr 1; // div 2
end; // {end while}

end;

66
...find the greatest common factor (GCF) of integers?

Author: Peter Bone

Homepage: http://www.geocities.com/peter_bone_uk

{
The greatest common factor, or GCF, is the greatest factor
that divides two numbers.
}

{
Der GGT zweier Zahlen ist der gr te gemeinsame Teiler
dieser Zahlen, also die gr te Zahl, durch die beide
Zahlen teilbar sind.
}

uses
math;

// Find the greatest common factor of two integers

function TForm1.GCF(A, B: Integer): Integer;


var
Lfactor: Integer;
begin
// Return -1 if either value is zero or negative
if (A < 1) or (B < 1) then
begin
Result := -1;
Exit;
end;
// if A = B then this is the GCF
if A = B then
begin
Result := A;
Exit;
end;
Result := 1;
for Lfactor := trunc(max(A, B) / 2) downto 2 do
begin
if (frac(A / Lfactor) = 0) and (frac(B / Lfactor) = 0) then
begin
Result := Lfactor;
Exit; // GCF has been found. No need to continue
end;
end;
end;

// Example:
procedure TForm1.Button1Click(Sender: TObject);
var
Res: Integer;
begin
Res := GCF(120, 30);
ShowMessage(Inttostr(Res));
end;

67
{******************}

// Find the greatest common factor of an array of integers


function TForm1.GCFarray(A: array of Integer): Integer;
var
Llength, Lindex, Lfactor: Integer;
begin
Llength := Length(A);

// Return -1 if any value is zero or negative


for Lindex := 0 to Llength - 1 do
begin
if A[Lindex] < 1 then
begin
Result := -1;
Exit;
end;
end;

// if all elements are equal then this is the GCF


Lindex := 1;
while (Lindex < Llength) and (A[Lindex] = A[0]) do Inc(Lindex);
if Lindex = Llength then
begin
Result := A[0];
Exit;
end;

Result := 1;

for Lfactor := trunc(ArrayMax(A) / 2) downto 2 do


begin
Lindex := 0;
while (Lindex < Llength) and
(frac(A[Lindex] / Lfactor) = 0) do Inc(Lindex);
if Lindex = Llength then
begin
Result := Lfactor;
Exit; // GCF has been found. No need to continue
end;
end;
end;

// find the maximum value in an array of integers


function TForm1.ArrayMax(Aarray: array of Integer): Integer;
var
Lpos: Integer;
begin
Result := 0;
for Lpos := 0 to Length(Aarray) - 1 do
if Aarray[Lpos] > Result then
Result := Aarray[Lpos];
end;

68

You might also like