Класс для манипулирования списком вещественных чиселDelphi , Компоненты и Классы , КлассыКласс для манипулирования списком вещественных чисел
Автор: Vitaly Sergienko { **** UBPFD *********** by delphibase.endimus.com **** >> Класс для манипулирования списком вещественных чисел Класс для манипулирования списком вещественных чисел Класс TxFloatList позволяет оперировать динамическим списком вещественных чисел (тип Double) двойной точности. Применение аналогично использованию TStringList :-) Ограничения Проверенно на Delphi 6.0 + SP2. Зависимости: Classes Автор: softland, softland@zmail.ru, Волгоград Copyright: Vitaly Sergienko (softland@zmail.ru) Дата: 4 августа 2002 г. ***************************************************** } (* (c) Vitaly Sergienko (softland@zmail.ru) created(10 Feb 1996) lastmod(4 Aug 2002) Базовая версия исходного кода взята из книги, название уже не помню :-( и обес- печивала работу с целыми числами ver 1.0.4 Класс для манипулирования списком вещественных чисел Класс TxFloatList позволяет оперировать динамическим списком вещественных чисел (тип Double) двойной точности. Как можно применить Применение аналогично использованию TStringList :-) Ограничения Проверенно на Delphi 6.0 + SP2. Форматирование комментариев подготовлено для обработки исходников программой rjPasDoc *) unit floatlist; interface uses Classes; const (* Минимальное значение для типа double *) _FLOAT_MIN_ = -1.1E4932; (* Максимальное значение для типа double *) _FLOAT_MAX_ = 1.1E4932; (* Точность в рабочих вычислениях *) _EPSILON_ = 0.00001; (* Константа возвращаемая при успешном завершении функции *) _OK_ = 1; (* Константа возвращаемая при неудачном завершении функции *) _ERROR_ = 0; type (* Класс генерации exception при переполнении списка *) EOutOfRange = class(EListError); (* Класс обеспечивает создание, удаление, вставку и доступ к элементам динами- ческого списка вещественных чисел. Дополнительно поддерживается сортировка списка, поиск минимального и макси- мального значений в списке. Особенностью реализации списка является введение понятия несуществующего зна- чения "property Null". Данное свойство определяет значение, которое не участ- вует в операциях получения min и max списка. Второй особенностью списка является работа с определенной точностью, значение выведено в константу _EPSILON_. Поиск и сортировка осуществляются без использования свойства NULL и _EPSILON_ *) TxFloatList = class(TPersistent) private FList: TList; FDuplicates: TDuplicates; FNULL: double; FMin: double; FMax: double; FSizeOfFloat: integer; FSorted: Boolean; protected procedure DefineProperties(Filer: TFiler); override; function GetCount(): integer; function GetItem(Index: integer): double; procedure SetItem(Index: integer; Value: double); virtual; procedure SetMin(Value: double); procedure SetMax(Value: double); procedure Sort(); virtual; public constructor Create(); destructor Destroy(); override; procedure ReadMin(Reader: TReader); procedure WriteMin(Writer: TWriter); procedure ReadMax(Reader: TReader); procedure WriteMax(Writer: TWriter); procedure ReadFloats(Reader: TReader); procedure WriteFloats(Writer: TWriter); procedure SetSorted(Value: Boolean); procedure QuickSort(L, R: integer); function Find(N: double; var Index: integer): Boolean; virtual; function Add(Value: double): integer; virtual; procedure AddFloats(List: TxFloatList); virtual; procedure Assign(Source: TPersistent); override; procedure Clear(); virtual; procedure Delete(Index: integer); virtual; function Equals(List: TxFloatList): Boolean; procedure Exchange(Index1, Index2: integer); virtual; function IndexOf(N: double): integer; virtual; procedure Insert(Index: integer; Value: double); virtual; (* Помещает пустые значения в список начиная с позиции iFirst в количестве iCount *) function InsertNulls(iFirst, iCount: integer; _null: single): integer; procedure Move(CurIndex, NewIndex: integer); virtual; // определение max среди хранимых данных function FindMax(): double; // определение min среди хранимых данных function FindMin(): double; (* Заменяет все отрицательные значения на нулевое *) function ReplaceNegativeToNULL(): integer; (* Заменяет все значения ThisValue на ToValue, с точностью Prec *) function ReplaceValToVal(ThisValue, ToValue, Prec: double): integer; function ReplaceGreateToVal(ThisValue, ToValue, Prec: double): integer; function ReplaceLessToVal(ThisValue, ToValue, Prec: double): integer; (* Инвертирует знак всех значений*) function InvertValues(): integer; (* Меняет, инвертирует порядок всех элементов в списке *) function Reverse(): integer; property Duplicates: TDuplicates read FDuplicates write FDuplicates; property Count: integer read GetCount; property Items[Index: integer]: double read GetItem write SetItem; default; property Min: double read FMin write SetMin; property Max: double read FMax write SetMax; property Null: double read FNULL write FNULL; property Sorted: Boolean read FSorted write SetSorted; end; (********************************************************************) implementation uses WinTypes; constructor TxFloatList.Create; begin inherited Create; FList := TList.Create; FSizeOfFloat := SizeOf(double); end; destructor TxFloatList.Destroy; begin Clear; FList.Free; inherited Destroy; end; procedure TxFloatList.Assign(Source: TPersistent); begin if Source is TxFloatList then begin Clear; AddFloats(TxFloatList(Source)); end else inherited Assign(Source); end; procedure TxFloatList.DefineProperties(Filer: TFiler); begin Filer.DefineProperty('Min', ReadMin, WriteMin, min <> 0); Filer.DefineProperty('Max', ReadMax, WriteMax, FMax <> 0); Filer.DefineProperty('Floats', ReadFloats, WriteFloats, Count > 0); end; procedure TxFloatList.ReadMin(Reader: TReader); begin FMin := Reader.ReadFloat; end; procedure TxFloatList.WriteMin(Writer: TWriter); begin Writer.WriteFloat(FMin); end; procedure TxFloatList.ReadMax(Reader: TReader); begin FMax := Reader.ReadFloat; end; procedure TxFloatList.WriteMax(Writer: TWriter); begin Writer.WriteFloat(FMax); end; procedure TxFloatList.ReadFloats(Reader: TReader); begin Reader.ReadListBegin(); (* Считывание маркера начала списка *) Clear; (* Очистка иекущего списка *) while not Reader.EndOfList do Add(Reader.ReadFloat()); (* Добавление к списку хранящихся чисед *) Reader.ReadListEnd(); (* Считывание маркера конца списка *) end; procedure TxFloatList.WriteFloats(Writer: TWriter); var i: integer; begin Writer.WriteListBegin(); (* Вписываем маркер начала списка *) for i := 0 to Count - 1 do Writer.WriteFloat(GetItem(I)); (* Запись всех чисел из списка в Writer *) Writer.WriteListEnd(); (* Вписываем маркер конца списка *) end; procedure TxFloatList.SetSorted(Value: Boolean); begin if FSorted <> Value then begin if Value then Sort(); FSorted := Value; end; end; function TxFloatList.GetCount: integer; begin Result := FList.Count; end; function TxFloatList.GetItem(Index: integer): double; begin Result := PDouble(FList.Items[Index])^; end; procedure TxFloatList.SetItem(Index: integer; Value: double); begin { if ( FMin <> FMax ) and ( ( Value < Fmin ) or ( Value > FMax ) ) then raise EOutOfRange.CreateFmt( 'Value must be within %d..%d', [FMin, FMax]);} PDouble(FList.Items[Index])^ := Value; end; procedure TxFloatList.SetMin(Value: double); var i: integer; begin if Value <> FMin then begin for i := 0 to Count - 1 do if GetItem(i) < Value then raise EOutOfRange.CreateFmt('Unable to set new minimum value. ' + #13 + 'List contains values below %d', [Value]); FMin := Value; if FMin > FMax then FMax := FMin; end; end; procedure TxFloatList.SetMax(Value: double); var i: integer; begin if Value <> FMax then begin for i := 0 to Count - 1 do if GetItem(i) > Value then raise EOutOfRange.CreateFmt('Unable to set new maximum value. '#13 + 'List contains values above %d', [Value]); FMax := Value; if FMax < FMin then FMin := FMax; end; end; procedure TxFloatList.AddFloats(List: TxFloatList); var i: integer; begin for i := 0 to Pred(List.Count) do Add(List[i]); end; function TxFloatList.Add(Value: double): integer; begin Insert(Count, Value); result := Count; end; procedure TxFloatList.Clear; var i: integer; begin for i := 0 to Pred(FList.Count) do Dispose(PDouble(FList.Items[i])); FList.Clear; end; procedure TxFloatList.Delete(Index: integer); begin Dispose(PDouble(FList.Items[Index])); FList.Delete(Index); end; function TxFloatList.Equals(List: TxFloatList): Boolean; var i, Count: integer; begin Count := GetCount; if Count <> List.GetCount then Result := False else begin i := 0; while (i < Count) and (GetItem(i) = List.GetItem(i)) do INC(i); Result := i = Count; end; end; procedure TxFloatList.Exchange(Index1, Index2: integer); begin FList.Exchange(Index1, Index2); end; function TxFloatList.Find(N: double; var Index: integer): Boolean; var l, h, i: integer; begin Result := False; l := 0; h := Count - 1; while l <= h do begin i := (l + h) shr 1; if PDouble(FList[i])^ < N then l := i + 1 else begin h := i - 1; if PDouble(FList[i])^ = N then begin Result := True; if Duplicates <> dupAccept then l := i; end; end; end; Index := l; end; function TxFloatList.IndexOf(N: double): integer; var i: integer; begin Result := -1; if not Sorted then begin for i := 0 to Pred(GetCount) do if GetItem(i) = N then begin Result := i; exit; end; end else if Find(N, i) then Result := i; end; procedure TxFloatList.Insert(Index: integer; Value: double); var P: PDouble; begin //comment ad 12.04.2001 softland // if (FMin <> FMax) and (( Value < FMin ) or (Value > FMax )) then // raise EOutOfRange.CreateFmt( 'Value must be within %f..%f', [FMin, FMax ]); NEW(p); p^ := Value; FList.Insert(Index, P); end; procedure TxFloatList.Move(CurIndex, NewIndex: integer); begin FList.Move(CurIndex, NewIndex); end; procedure TxFloatList.QuickSort(L, R: integer); var i, j: integer; p: PDouble; begin i := L; j := R; P := PDouble(FList[(L + R) shr i]); repeat while PDouble(FList[i])^ < P^ do INC(i); while PDouble(FList[j])^ > P^ do DEC(j); if i <= j then begin FList.Exchange(i, j); INC(i); DEC(j); end; until i > l; if L < j then QuickSort(L, j); if i < R then Quicksort(i, R); end; procedure TxFloatList.Sort(); begin if not Sorted and (FList.Count > 1) then QuickSort(0, FList.Count - 1); end; function TxFloatList.FindMax(): double; // определение max среди хранимых данных var i: integer; v: double; begin FMax := _FLOAT_MIN_; for i := 0 to Count - 1 do begin v := GetItem(i); if abs(v - FNULL) > _EPSILON_ then if v > FMax then FMax := v; end; if abs(FMax - _FLOAT_MIN_) < _EPSILON_ then FMax := FNULL; result := FMax; end; function TxFloatList.FindMin: double; //определение min среди хранимых данных var i: integer; v: double; begin { for i := 0 to Count-1 do if GetItem(i) <> FNULL then begin FMin := GetItem(i); break; end;} FMin := _FLOAT_MAX_; for i := 0 to Count - 1 do begin v := GetItem(i); if abs(v - FNULL) > _EPSILON_ then if v < FMin then FMin := v; end; if abs(FMin - _FLOAT_MAX_) < _EPSILON_ then FMin := FNULL; result := FMin; end; (* Заменяет все отрицательные значения на нулевое *) function TxFloatList.ReplaceNegativeToNULL: integer; var i: integer; begin result := 0; for i := 0 to Count - 1 do begin if Items[i] < 0 then begin Items[i] := self.Null; inc(result); end; end; end; function TxFloatList.ReplaceValToVal(ThisValue, ToValue, Prec: double): integer; var i: integer; begin result := 0; for i := 0 to Count - 1 do begin if abs(Items[i] - ThisValue) < Prec then begin Items[i] := ToValue; inc(result); end; end; end; function TxFloatList.ReplaceLessToVal(ThisValue, ToValue, Prec: double): integer; var i: integer; begin result := 0; for i := 0 to Count - 1 do begin if Items[i] < ThisValue then begin Items[i] := ToValue; inc(result); end; end; end; function TxFloatList.ReplaceGreateToVal(ThisValue, ToValue, Prec: double): integer; var i: integer; begin result := 0; for i := 0 to Count - 1 do begin if Items[i] > ThisValue then begin Items[i] := ToValue; inc(result); end; end; end; function TxFloatList.InvertValues(): integer; var i: integer; begin result := _OK_; for i := 0 to Count - 1 do items[i] := -items[i]; end; function TxFloatList.Reverse(): integer; var i, j: integer; begin result := _OK_; i := 0; j := Count - 1; repeat self.Exchange(i, j); inc(i); dec(j); until i >= j; end; (* Заполнение в заданных пределах значениями NULL Подразумевается положительное и возрастающее поведение глубины, т.е. 0<STRT<STOP Еи _strt > текущего min или _stop < текущего максимума содержащегося в списке, то функция возвращает _ERROR_ Еи _null не совпадает со значением принятым за NULL в списке, то это игнорируется Заполнение ведется с текущим шагом списка *) function TxFloatList.InsertNulls(iFirst, iCount: integer; _null: single): integer; var k: integer; begin for k := 1 to iCount do begin Insert(iFirst, _null); inc(iFirst); end; result := _OK_; end; end. Это модуль Delphi, реализующий класс Некоторые ключевые функции:
Вопреки тому, что реализация quite extensive, с комментариями и заметками по всему коду, я обнаружил несколько потенциальных проблем:
Класс TxFloatList - это обобщение списков вещественных чисел для использования в программировании на языке Delphi, позволяющее оперировать динамическим списком вещественных чисел (тип Double) двойной точности. Комментарии и вопросыПолучайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
|
||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |