Avatar billede lanstorp Nybegynder
01. september 2002 - 15:45 Der er 5 kommentarer og
1 løsning

Median beregning

Har lavet en funktion til beregningen af medianen af en tal-række.

function MedianDouble (dZ: array of Double): Double;
var
  StringList: TStringList;
  i, iNumPoints: integer;
  dTemp1, dtemp2: double;
begin
  iNumPoints := High(dZ);
  StringList := TStringList.Create;
  for i := 0 to iNumPoints - 1 do
  begin
    StringList.Insert(i,FloatToStr(dZ[i]));
  end;

  StringList.Sorted := TRUE;  // sort to get the median value

  if Odd(iNumPoints-1) then
  begin
    //ShowMessage('Odd');
    Result := StrToFloat(StringList[iNumPoints div 2]);
  end
  else
  begin
    //ShowMessage('Even');
    dTemp1 := StrToFloat(StringList[(iNumPoints div 2)-1]);
    dTemp2 := StrToFloat(StringList[(iNumPoints div 2)]);
    Result := (dTemp1 + dTemp2) / 2;
  end;

  StringList.Free;
end;


Den funker bare ikke helt. Nogle tal-genier der kan se hvorfor. EFGs har en algoritme, men den er langsom og kun til integers.

http://homepages.borland.com/efg2lab/Library/Delphi/MathFunctions/StatisticsLibrary.pas.TXT
Avatar billede nico26 Nybegynder
01. september 2002 - 17:21 #1
function CompareDouble(Double1, Double2 : Pointer) : Integer;
var
  D1, D2 : Double;
begin
  D1 := Double(Double1^);
  D2 := Double(Double2^);

  if D1 < D2 then
    Result := -1
  else if D1 > D2 then
    Result := 1
  else
    Result := 0;
end;

function MedianDouble(const dZ : array of Double) : Double;
var
  iNumPoints : Integer;
  Numbers : TList;
  i : Integer;
  dTemp1, dTemp2 : Double;
begin
  iNumPoints := High(dZ) + 1;

  Numbers := TList.Create;
  try
    for i := 0 to iNumPoints - 1 do
      Numbers.Add(@dZ[i]);

    Numbers.Sort(@CompareDouble);

    if Odd(iNumPoints) then
      Result := Double(Numbers[iNumPoints div 2]^)
    else begin
      dTemp1 := Double(Numbers[(iNumPoints div 2)-1]^);
      dTemp2 := Double(Numbers[(iNumPoints div 2)]^);
      Result := (dTemp1 + dTemp2) / 2;
    end;
  finally
    Numbers.Free;
  end;
end;
Avatar billede nca Juniormester
01. september 2002 - 17:39 #2
Du skal rette denne linje "if Odd(iNumPoints-1) then" til
if Odd(iNumPoints) then
Avatar billede lanstorp Nybegynder
01. september 2002 - 18:14 #3
>>nico22
Linien: Numbers.Sort(@CompareDouble);
giver kompilerfejl: Variable required ???
>>nca
Første element i et array har index nul
Avatar billede nca Juniormester
01. september 2002 - 18:22 #4
>> Det kan godt være, men det virker alligevel. Den tæller jo antal tal og her begynder den ved 1. Har du prøvet at lave ændringen?
Avatar billede lanstorp Nybegynder
01. september 2002 - 22:29 #5
>>nca
... tæller antal tal ???
High levere den højeste array index værdi, test selv:

procedure TForm1.Button1Click(Sender: TObject);
const
  D : array[0..2] of integer = (1,2,3);
begin
  ShowMessage('High(D): ' + IntToStr(High(D)));
end;

>> nico22
Kan du se hvad der går galt med den pointer.
Avatar billede lanstorp Nybegynder
01. september 2002 - 22:39 #6
hehehe,
smed den en funktion ind i den anden og det rykkede. Takker.

function MedianDouble(const dZ : array of Double) : Double;
  function CompareDouble(Double1, Double2 : Pointer) : Integer;
  var
  D1, D2 : Double;
  begin
    D1 := Double(Double1^);
    D2 := Double(Double2^);

    if D1 < D2 then
      Result := -1
    else if D1 > D2 then
      Result := 1
    else
      Result := 0;
  end;

var
  iNumPoints : Integer;
  Numbers : TList;
  i : Integer;
  dTemp1, dTemp2 : Double;
begin
  iNumPoints := High(dZ) + 1;

  Numbers := TList.Create;
  try
    for i := 0 to iNumPoints - 1 do
      Numbers.Add(@dZ[i]);

    Numbers.Sort(@CompareDouble);

    if Odd(iNumPoints) then
      Result := Double(Numbers[iNumPoints div 2]^)
    else begin
      dTemp1 := Double(Numbers[(iNumPoints div 2)-1]^);
      dTemp2 := Double(Numbers[(iNumPoints div 2)]^);
      Result := (dTemp1 + dTemp2) / 2;
    end;
  finally
    Numbers.Free;
  end;
end;
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester