最近写了个Shell排序的程序,并放在BackgroundTask中运行。对于Simotion来说,算法占用的空间挺大,如果编译的时候提示BackgroundTask的Stack Size错误,请在执行系统的TaskConfiguration中将BackgroundTask的StackSize改大些。程序很简单,有需要用到的话复制粘贴过去就行了,需要注意的是以下有两个st文件,所以请分别粘贴到不同名字的 .st文件中。
//文件一:Random.st
//用于产生随机数据的Function,这两个Function要联合使用,使用方法请参考Program sort中的使用。
//===Random============================================================
//SIEMENS AG
//(c)Copyright 2007 All Rights Reserved
//-----------------------------------------------------------------------------------
// project name:
// file name: Random.xml
// library: LibBasic
// system:
// version: SIMOTION / Scout V4.1
// restrictions:
// requirements: hardware independet, no technological packages
// functionality:
//-----------------------------------------------------------------------------------
// change log table:
// version date expert in charge changes applied
// 01.00.00 not specified first created
// 01.01.00 n.s.
// 01.02.00 n.s.
// 02.00.00 20.01.07 C. Fecke A&D B18 changes of form, variables, ...
// 02.01.00 20.04.07 C. Fecke A&D B18 new assignment (LibBasic)
// 02.02.00 07.08.07 C. Fecke A&D B18 Changes with reference to the styleguide V3.5
//=======================================================================
INTERFACE
// ----------- Export ---------------------------------------------------------
FUNCTION FCRandom; // creates a random number between 0.1 to 1 (LREAL)
FUNCTION FCRandomize; // inits the random generator
END_INTERFACE
IMPLEMENTATION
// ----------- Unit Global Constants ----------------------------------------
VAR_GLOBAL CONSTANT
A_RANDOM : DINT := 16807;
M_RANDOM : DINT := 2147483647;
Q_RANDOM : DINT := 127773; // m div a
R_RANDOM : DINT := 2836; // m mod a
END_VAR
// ----------- Unit Global Variables ----------------------------------------
VAR_GLOBAL
giRandomSeed : DINT := 1;
END_VAR
// ============================================================================
// ----------- Functions ------------------------------------------------------
// ============================================================================
FUNCTION FCRandom : LREAL
// ----------------------------------------------------------------------------
// (A&D SE WKC A FA / Chemnitz)
// ----------------------------------------------------------------------------
// functionality: creates a random number between 0.1 to 1 (LREAL)
// You should init the generator with
// FCRandomize(initial seed := 1..2147483646) before first call.
// The same initial seed create the same numerical series.
// Maxint must be greater than OR equal TO 2**31 - 1
// The created numerical series are uniformly distrubeted.
// assignment: This function can be used in any kind of task.
// ----------------------------------------------------------------------------
// change log table:
// version date expert in charge changes applied
// 02.00.00 20.01.07 C.Fecke A&D B18 changes of form, variables, ...
// ============================================================================
// The following random number generator is an implementation of the
// Minimum Standard Generator recommended in
// Random Number Generators: Good ones are hard to find
// Stephen K Park & Keith W Miller
// Communications OF the ACM, Oct 88, Vol 31 No 10 1192 - 1201
VAR
iLo : DINT;
iHi : DINT;
iTest : DINT;
END_VAR
// calculate the new seed
iHi := giRandomSeed / Q_RANDOM;
iLo := giRandomSeed MOD Q_RANDOM;
iTest := A_RANDOM * iLo - R_RANDOM * iHi;
// map seed on positive DINT number range (1..2147483646)
IF (iTest > 0) THEN // seed positiv ?
giRandomSeed := iTest;
ELSE // seed negativ ?
giRandomSeed := iTest + M_RANDOM;
END_IF;
// map random number (seed) on LREAL number range (0.0 .. 1.0)
FCRandom := DINT_TO_LREAL(giRandomSeed) / DINT_TO_LREAL(M_RANDOM);
RETURN;
END_FUNCTION
FUNCTION FCRandomize : VOID
// ----------------------------------------------------------------------------
// (A&D SE WKC A FA / Chemnitz)
// ----------------------------------------------------------------------------
// functionality: inits the random generator
// assignment: This function can be used in any kind of task.
// ----------------------------------------------------------------------------
// change log table:
// version date expert in charge changes applied
// 02.00.00 20.01.07 C.Fecke A&D B18 changes of form, variables, ...
// ============================================================================
VAR_INPUT
initSeed : DINT := 1; // integer between 1..2147483646
END_VAR
IF (initSeed < 1) THEN // seed too small ?
giRandomSeed := 1; // limit seed
ELSIF (initSeed > 2147483646) THEN // seed too big ?
giRandomSeed := 2147483646; // limit seed
ELSE // seed in range?
giRandomSeed := initSeed; // take seed
END_IF;
RETURN;
END_FUNCTION
END_IMPLEMENTATION
// 文件二 :ST_Sort.st
//该st文件中的程序Sort分配到backgroundtask
INTERFACE
USES random;
FUNCTION FcShellSort;
PROGRAM Sort;
END_INTERFACE
IMPLEMENTATION
VAR_GLOBAL
mySizeofArray: DINT;
Increment : DINT;
j,m: DINT;
temp:LREAL;
tempArray:ARRAY[0..8000] OF LREAL;
END_VAR
//***********************************************************************
// function ShellSort
//***********************************************************************
FUNCTION FcShellSort :ARRAY[0..8000]OF LREAL
VAR_INPUT
myArray : ARRAY[0..8000] OF LREAL;
END_VAR
(*
VAR
mySizeofArray: DINT;
Increment : DINT;
j,m: DINT;
temp:LREAL;
tempArray:ARRAY[0..8000] OF LREAL;
END_VAR*)
tempArray:=myArray; //put the input array to a temp array
mySizeofArray:=_sizeof(myArray)/_sizeof(myArray[0]);//get the size of array
Increment:=mySizeofArray; //init Increment with the size of array
REPEAT
Increment:=Increment/3+1; // the fomular to change the Increment
FOR j:=Increment TO mySizeofArray-1 BY 1 DO
temp:=tempArray[j];
m:=j-Increment;
WHILE tempArray[m]>temp DO
tempArray[m+Increment]:=tempArray[m];
m:=m-Increment;
IF m<0 OR m>=mySizeofArray THEN
EXIT;
END_IF;
END_WHILE;
tempArray[m+Increment]:=temp;
END_FOR;
UNTIL Increment<=1
END_REPEAT;
FcShellSort:=tempArray;
END_FUNCTION
PROGRAM sort
VAR
ArrayData:ARRAY[0..8000] OF LREAL; // to be sorted
aData: ARRAY[0..8000] OF LREAL; // result after sorting
i: DINT;
CalculateTrig: r_trig;
StartCal: BOOL:=FALSE;
END_VAR
CalculateTrig(clk:=StartCal);
IF CalculateTrig.q THEN //start calculation
//create an array of random data
fcrandomize(initseed:=345);
FOR i:=0 TO 8000 BY 1 DO
ArrayData[i]:=fcrandom()*1000.0;
END_FOR;
//call the function to sort
aData:= FcShellSort(ArrayData);
END_IF;
END_PROGRAM
END_IMPLEMENTATION