Subversion Repositories delphiutils

Rev

Rev 34 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. unit Main;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.   Dialogs, StdCtrls, ExtCtrls;
  8.  
  9. type
  10.   TForm1 = class(TForm)
  11.     GroupBox1: TGroupBox;
  12.     Edit1: TEdit;
  13.     Label1: TLabel;
  14.     Edit2: TEdit;
  15.     GroupBox2: TGroupBox;
  16.     Edit3: TEdit;
  17.     Label3: TLabel;
  18.     Edit4: TEdit;
  19.     GroupBox3: TGroupBox;
  20.     Label2: TLabel;
  21.     Label4: TLabel;
  22.     Panel1: TPanel;
  23.     Label5: TLabel;
  24.     Label6: TLabel;
  25.     RadioButton1: TRadioButton;
  26.     RadioButton2: TRadioButton;
  27.     Edit5: TEdit;
  28.     Edit6: TEdit;
  29.     procedure Edit3Change(Sender: TObject);
  30.     procedure Edit4Change(Sender: TObject);
  31.     procedure SourceChange(Sender: TObject);
  32.     procedure FormShow(Sender: TObject);
  33.     procedure RadioButton1Click(Sender: TObject);
  34.     procedure RadioButton2Click(Sender: TObject);
  35.   private
  36.     procedure UpdateFract(A, B: Extended);
  37.     procedure AllEnabled(AEnabled: boolean; AExcept: TObject);
  38.   end;
  39.  
  40. var
  41.   Form1: TForm1;
  42.  
  43. implementation
  44.  
  45. {$R *.dfm}
  46.  
  47. {$DEFINE ALLOW_A_IS_ZERO}
  48. {$DEFINE ALLOW_B_IS_ZERO}
  49.  
  50. // Setzt einen Text ohne OnChange() auszulösen
  51. procedure SetText(AEdit: TEdit; AText: String);
  52. var
  53.   oc: TNotifyEvent;
  54. begin
  55.   oc := AEdit.OnChange;
  56.   try
  57.     AEdit.OnChange := nil;
  58.     AEdit.Text := AText;
  59.   finally
  60.     AEdit.OnChange := oc;
  61.   end;
  62. end;
  63.  
  64. // http://www.delphi-library.de/viewtopic.php?p=288665#288665
  65. procedure FloatToFrac(const x: Extended; out Numerator, Denominator: Int64);
  66. const
  67.  tol = 1e-12; // Fehlertoleranz
  68. var
  69.   p, lastp, q, lastq, ptemp, qtemp, u, err, d: Extended;
  70. begin
  71.   // Initialisierung
  72.   p := 1;
  73.   q := 0;
  74.   lastp := 0;
  75.   lastq := 1;
  76.   u := x;
  77.  
  78.   repeat
  79.     // Einen ganzzahligen Anteil abspalten
  80.     d := round(u);
  81.     u := u - d;
  82.  
  83.     // Update von p und q: Kettenbruch (siehe unten) nachführen. Es gilt: p/q ~= x
  84.     ptemp := p*d+lastp;
  85.     qtemp := q*d+lastq;
  86.     lastp := p;
  87.     lastq := q;
  88.     p := ptemp;
  89.     q := qtemp;
  90.  
  91.     // Approximationsfehler
  92.     err := abs(p/q-x);
  93.  
  94.     // Abbruchkriterien
  95.     if (u=0) or (err<tol) or (x+err/4=x {sic!}) then  // (*)
  96.      break;
  97.  
  98.     // Bruch umkehren
  99.     u := 1/u;
  100.   until false;
  101.  
  102.   // Vor Integerkonversion auf Bereich überprüfen
  103.   if (p>high(Int64)) or (q>high(Int64)) or
  104.      (p<low(Int64)) or (p<low(Int64)) then
  105.     raise EIntOverflow.Create('FloatToFrac: Integer conversion overflow.');
  106.  
  107.   // Vorzeichen von Nenner zum Zähler
  108.   if q < 0 then
  109.    Numerator := -Trunc(p) else
  110.    Numerator := Trunc(p);
  111.   Denominator := abs(Trunc(q));
  112. end;
  113.  
  114. procedure TForm1.UpdateFract(A, B: Extended);
  115. var
  116.   P, Q: Int64;
  117. begin
  118.   {$IFDEF ALLOW_B_IS_ZERO}
  119.   if B = 0 then
  120.   begin
  121.     Label2.Caption := FloatToStr(A);
  122.     Label4.Caption := FloatToStr(B);
  123.     Label6.Caption := '?';
  124.     exit;
  125.   end;
  126.   {$ENDIF}
  127.  
  128.   FloatToFrac(A / B, P, Q);
  129.   Label2.Caption := IntToStr(P);
  130.   Label4.Caption := IntToStr(Q);
  131.   Label6.Caption := FloatToStr(A / B);
  132. end;
  133.  
  134. procedure TForm1.AllEnabled(AEnabled: boolean; AExcept: TObject);
  135. begin
  136.   if AExcept <> Edit1 then
  137.     Edit1.Enabled := AEnabled;
  138.  
  139.   if AExcept <> Edit2 then
  140.     Edit2.Enabled := AEnabled;
  141.  
  142.   {$IFDEF ALLOW_A_IS_ZERO}
  143.   if Edit1.Text <> '0' then
  144.   begin
  145.   {$ENDIF}
  146.   if AExcept <> Edit3 then
  147.     Edit3.Enabled := AEnabled;
  148.   {$IFDEF ALLOW_A_IS_ZERO}
  149.   end;
  150.   {$ENDIF}
  151.  
  152.   {$IFDEF ALLOW_B_IS_ZERO}
  153.   if Edit2.Text <> '0' then
  154.   begin
  155.   {$ENDIF}
  156.   if AExcept <> Edit4 then
  157.     Edit4.Enabled := AEnabled;
  158.   {$IFDEF ALLOW_B_IS_ZERO}
  159.   end;
  160.   {$ENDIF}
  161. end;
  162.  
  163. procedure TForm1.SourceChange(Sender: TObject);
  164. var
  165.   A, B: Extended;
  166. begin
  167.   TEdit(Sender).Color := clWindow;
  168.   AllEnabled(true, Sender);
  169.   try
  170.     A := StrToFloat(Edit1.Text);
  171.     B := StrToFloat(Edit2.Text);
  172.  
  173.     {$IFDEF ALLOW_A_IS_ZERO}
  174.     {$IFDEF ALLOW_B_IS_ZERO}
  175.     if (A = 0) and (B = 0) then
  176.     begin
  177.       raise Exception.Create('Both source values cannot be zero.');
  178.     end;
  179.     {$ENDIF}
  180.     {$ENDIF}
  181.  
  182.     if RadioButton2.Checked then
  183.     begin
  184.       {$IFDEF ALLOW_A_IS_ZERO}
  185.       if A = 0 then
  186.       begin
  187.         RadioButton1.Enabled := false;
  188.         RadioButton2.Enabled := false;
  189.         SetText(Edit3, '0');
  190.         Edit5.Text := '0';
  191.         Edit3.Enabled := false;
  192.         Edit5.Enabled := false;
  193.       end
  194.       else
  195.       begin
  196.         RadioButton1.Enabled := true;
  197.         RadioButton2.Enabled := true;
  198.         Edit3.Enabled := true;
  199.         Edit5.Enabled := true;
  200.       {$ENDIF}
  201.       SetText(Edit3, FloatToStr(A / B * StrToFloat(Edit4.Text)));
  202.       Edit5.Text := IntToStr(Round(StrToFloat(Edit3.Text)));
  203.       {$IFDEF ALLOW_A_IS_ZERO}
  204.       end;
  205.       {$ENDIF}
  206.     end
  207.     else
  208.     begin
  209.       {$IFDEF ALLOW_B_IS_ZERO}
  210.       if B = 0 then
  211.       begin
  212.         RadioButton1.Enabled := false;
  213.         RadioButton2.Enabled := false;
  214.         SetText(Edit4, '0');
  215.         Edit6.Text := '0';
  216.         Edit4.Enabled := false;
  217.         Edit6.Enabled := false;
  218.       end
  219.       else
  220.       begin
  221.         RadioButton1.Enabled := true;
  222.         RadioButton2.Enabled := true;
  223.         Edit4.Enabled := true;
  224.         Edit6.Enabled := true;
  225.       {$ENDIF}
  226.       SetText(Edit4, FloatToStr(B / A * StrToFloat(Edit3.Text)));
  227.       Edit6.Text := IntToStr(Round(StrToFloat(Edit4.Text)));
  228.       {$IFDEF ALLOW_B_IS_ZERO}
  229.       end;
  230.       {$ENDIF}
  231.     end;
  232.  
  233.     UpdateFract(A, B);
  234.   except
  235.     TEdit(Sender).Color := clRed;
  236.     AllEnabled(false, Sender);
  237.   end;
  238. end;
  239.  
  240. procedure TForm1.Edit3Change(Sender: TObject);
  241. var
  242.   A, B: Extended;
  243. begin
  244.   Edit3.Color := clWindow;
  245.   AllEnabled(true, Sender);
  246.   try
  247.     A := StrToFloat(Edit1.Text);
  248.     B := StrToFloat(Edit2.Text);
  249.  
  250.     SetText(Edit4, FloatToStr(B / A * StrToFloat(Edit3.Text)));
  251.     Edit6.Text := IntToStr(Round(StrToFloat(Edit4.Text)));
  252.  
  253.     Edit5.Text := IntToStr(Round(StrToFloat(Edit3.Text)));
  254.   except
  255.     Edit3.Color := clRed;
  256.     AllEnabled(false, Sender);
  257.   end;
  258. end;
  259.  
  260. procedure TForm1.Edit4Change(Sender: TObject);
  261. var
  262.   A, B: Extended;
  263. begin
  264.   Edit4.Color := clWindow;
  265.   AllEnabled(true, Sender);
  266.   try
  267.     A := StrToFloat(Edit1.Text);
  268.     B := StrToFloat(Edit2.Text);
  269.  
  270.     SetText(Edit3, FloatToStr(A / B * StrToFloat(Edit4.Text)));
  271.     Edit5.Text := IntToStr(Round(StrToFloat(Edit3.Text)));
  272.  
  273.     Edit6.Text := IntToStr(Round(StrToFloat(Edit4.Text)));
  274.   except
  275.     Edit4.Color := clRed;
  276.     AllEnabled(false, Sender);
  277.   end;
  278. end;
  279.  
  280. procedure TForm1.FormShow(Sender: TObject);
  281. var
  282.   A, B: Extended;
  283. begin
  284.   A := StrToFloat(Edit1.Text);
  285.   B := StrToFloat(Edit2.Text);
  286.  
  287.   UpdateFract(A, B);
  288. end;
  289.  
  290. procedure TForm1.RadioButton1Click(Sender: TObject);
  291. begin
  292.   if StrToFloat(Edit2.Text) = 0 then
  293.   begin
  294.     Edit2.OnChange(Edit2);
  295.   end;
  296. end;
  297.  
  298. procedure TForm1.RadioButton2Click(Sender: TObject);
  299. begin
  300.   if StrToFloat(Edit1.Text) = 0 then
  301.   begin
  302.     Edit1.OnChange(Edit1);
  303.   end;
  304. end;
  305.  
  306. end.
  307.