Einzelnen Beitrag anzeigen

alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#63

Re: Quadratische Gleichungen vollständig lösen

  Alt 30. Jan 2010, 21:26
Zitat von gammatester:
Und ich verstehe Deine Ignoranz nicht: Statt zu fragen, was 'Re' und 'Im' bedeutet,
Wieso soll ich fragen, der Code soll es mir beantworten. Ich weiss ja nicht, für wen du so Code schreibst, aber ich steh doch nicht auf und lauf in der Abteilung herum, um den Knilch zu finden, der seine Variablen 're' und 'im' oder 'frzl' und 'mpft' nennnt? Gut, hier mag das noch aus dem Kontext hervorgehen, aber für ein T-u-t-o-r-i-a-l ist das etwas kryptisch, findest du nicht?

Zitat:
Das sind mathematische Bezeichnungen, die eigentlich schon auf dem Gymnasium bekannt sein sollten, spätestes im Studium, das auch nur ein wenig mit Mathe zu tun hat.
Hoho gammatester, halt mal die Luft an, ich zieh auch nicht über deine Herkunft oder deinen Codestil her.
Zitat von gammatester:
Re = Realteil, Im = Imaginärteil.
Und wieso *heißen* die Variablen dann nicht so?

Wenn das die deutschen Abkürzungen sind, was hat das dann in einem Code zu suchen, der vorgibt, englische Bezeichner zu verwenden?

Übrigens gammatester,
Zitat:
Und ich verstehe Deine Ignoranz nicht: ...
Hatten wir uns einander so vorgestellt?

Als Friedensangebot ein Vorschlag, der hoffentlich alle Kritikpunkte eliminiert, und die Erfahrungen in einen lesbaren und kommentarlosen Code zu gießt, der englische Bezeichner verwendet. Ich find sie auch schöner, ich gebs ja zu.

Über zu kurze, zu lange und korrekte Bezeichner lässt sich -wie immer- streiten. So weiss ich z.B. nicht, ob die Teilösung wirklich von Vieta ist (stand teilweise so im W.Mix-Code) und ob das mit den Diskriminanten immer stimmt.

Delphi-Quellcode:
unit QuadraticEquationSolver;

interface
uses
  SysUtils;

type
  EInvalidAccessException = class(Exception);
  TQuadraticEquationSolutionType = (stUndefined, stReal, stSingle, stComplex);
  TQuadraticEquationSolver = class
  private
    FSolutionType: TQuadraticEquationSolutionType;
    FSolution2: Double;
    FDiscriminant: Double;
    FSolution1: Double;
    FRealPart: Double;
    FComplexPart: Double;
    procedure SetSingleSolution(solution: Double);
    procedure SetRealSolutions(solution1, solution2: Double);
    procedure SetComplexSolution(realPart, complexPart: Double);
    procedure SolveUsingVietaFormula(p, q: Double);
    procedure SolveUsingTransformedFormula(p, q: Double);
    function IsAPositiveAndVeryLargeNumber(n: Double): Boolean;

    function GetSolution1: Double;
    function GetSolution2: Double;
    function GetRealPartOfSolution: Double;
    function GetComplexPartOfSolution: Double;
  public
    constructor Create;
    procedure Solve(a, b, c: Double);
    property SolutionType: TQuadraticEquationSolutionType read FSolutionType;
    property Solution1: Double read GetSolution1;
    property Solution2: Double read GetSolution2;
    property RealPartOfComplexSolition: Double read GetRealPartOfSolution;
    property ComplexPartOfComplexsolution: Double read GetComplexPartOfSolution;
  end;

implementation
uses Math;
{ TQuadraticEquationSolver }

{$Region 'Solving and Mathematics'}
procedure TQuadraticEquationSolver.Solve(a, b, c: Double);
var
  p,q : Double;

begin
  Assert (Not IsZero(a), 'a must be nonzero');
  p := b / a;
  q := c / a;
  if IsAPositiveAndVeryLargeNumber(p) then
    SolveUsingTransformedFormula(p, q)
  else begin
    FDiscriminant := sqr(p / 2) - q;
    case Sign(FDiscriminant) of
      +1: SolveUsingVietaFormula(p, q);
      0 : SetSingleSolution(-p / 2);
      -1: SetComplexSolution(-p / 2, Sqrt(abs(FDiscriminant)));
    end;
  end
end;

procedure TQuadraticEquationSolver.SolveUsingVietaFormula(p, q: Double);
var
  solution: Double;

begin
  solution := -p / 2 - sign(p) * sqrt(FDiscriminant);
  SetRealSolutions(solution, q / solution);
end;

procedure TQuadraticEquationSolver.SolveUsingTransformedFormula(p, q: Double);
var
  root: Double;

begin
  FDiscriminant := (1 / 4 - (q / p) / p);
  root := sqrt(FDiscriminant);
  SetRealSolutions(abs(p) - root, Abs(p) + root);
end;

function TQuadraticEquationSolver.IsAPositiveAndVeryLargeNumber(n: Double): Boolean;
begin
  Result := (abs(n) > sqrt(Math.MaxDouble));
end;

{$EndRegion}

{$Region 'Routines for setting the individual solutions'}
procedure TQuadraticEquationSolver.SetComplexSolution(realPart, complexPart: Double);
begin
  FSolutionType := stComplex;
  FRealPart := realPart;
  FComplexPart := complexPart;
end;

procedure TQuadraticEquationSolver.SetRealSolutions(solution1, solution2: Double);
begin
  FSolutionType := stReal;
  FSolution1 := solution1;
  FSolution2 := solution2;
end;

procedure TQuadraticEquationSolver.SetSingleSolution(solution: Double);
begin
  FSolutionType := stSingle;
  FSolution1 := solution;
  FSolution2 := solution;
end;
{$EndRegion}

{$Region 'Property access'}
function TQuadraticEquationSolver.GetSolution1: Double;
begin
  if SolutionType = stComplex then
    raise EInvalidAccessException.Create('Access only if solution is not complex');
  Result := FSolution1;
end;

function TQuadraticEquationSolver.GetSolution2: Double;
begin
  if SolutionType = stComplex then
    raise EInvalidAccessException.Create('Access only if solution is not complex');
  Result := FSolution2;
end;

function TQuadraticEquationSolver.GetRealPartOfSolution: Double;
begin
  if SolutionType <> stComplex then
    raise EInvalidAccessException.Create('Access only if solution is complex');
  Result := FRealPart;
end;

constructor TQuadraticEquationSolver.Create;
begin
  FSolutionType := stUndefined;
end;

function TQuadraticEquationSolver.GetComplexPartOfSolution: Double;
begin
  result := FComplexPart;
end;
{$EndRegion}
end.
Die Essenz ist die 'Solve'-Methode, die -denke ich- die Lösungsansätze von W.Mix und GT dokumentiert. Der Rest ist Mumpfe.
Das Dilemma, das Lösung sowohl reale als auch komplexe Lösungen liefert, habe ich habe ich durch unterschiedliche Properties versucht, zu lösen.

Reelle Lösungen (eine oder zwei) stehen in den Eigenschaften 'Solution1' und 'Solution2', die komplexen in 'RealPartOfComplexSolution' und 'ComplexPartOfComplexsolution'. Etwas lang, finde ich.

Aber so fragt keiner nach. Bei 'Solution1' und 'Solution2' vielleicht schon...

[edit]Seit wann werden Rechtschreibfehler vom DCC nicht erkannt? [/edit]
[edit]Fehler beim Refaktorisieren dank gammatester beseitigt. [/edit]
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat