Autor Beitrag
freedy
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 403
Erhaltene Danke: 1

Winows 7
Delphi XE
BeitragVerfasst: Fr 26.01.07 17:41 
Hallo Leute!

Ich habe folgendes Problem. Es soll eine logarithmische Skala gezeichnet werden. Als Test und zum Probieren habe ich auf eine Form einen TButton und ein TImage gesetzt.

Hier mein Code (leider nicht Kommentiert):

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Button1: TButton;
    ListBox1: TListBox;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function log10(Value : Double) : Double;
var
  res : Double;
begin
  Res := (ln(Value) / ln(10));
  if IsZero(Res, 0.00000001then
    Result := 0
  else
    Result := Res;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Erg : Double;
  I : Double;
  r : TRect;
  pix : Integer;
  Start : Double;
  Ende : Double;
  Step : Double;
  big : Integer;
  a, b : Extended;
begin
  Start := 0.1;
  Ende := 100;
  R.Right := Image1.Width;
  R.Bottom := Image1.Height;
  Image1.Picture.Bitmap.SetSize(Image1.Width, Image1.Height);
  with Image1.Picture.Bitmap.Canvas do
  begin
    FillRect(R);
    MoveTo(0, Image1.Height div 2);
    LineTo(Image1.Width, Image1.Height div 2);
  end;

  I := Start;
  Step := Start;

  big := Trunc((Image1.Width - 10) / (log10(Ende) - log10(Start)));

  while (I <= Ende) do
  begin
    Erg := log10(I);
    ListBox1.Items.Add(FloatToStr(Erg));

    pix := Trunc(big * (Erg - log10(Start)));
    with Image1.Picture.Bitmap.Canvas do
    begin
      MoveTo(pix + 5, Image1.Height div 2 - 5);
      LineTo(pix + 5, Image1.Height div 2 + 5);


      a := log10(I);
      b := Trunc(a);
      if (a = b) then
      begin
        TextOut(pix + 2, Image1.Height div 2 + 8, FloatToStr(I));
        Step := I;
      end;
      I := I + Step;
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Image1.Picture := TPicture.Create;
end;



Damit kann man beliebig rumspielen. Das tolle ist, er zeichnet alle Werte an die Skala, solange der Startwert nicht unter 1 geht. Warum?
Mit diesem Source erkennt er nicht, dass 1 = 1 sein soll, wenn die 10 gezeichnet werden soll. Ich weiß echt nicht weiter.

Gruß
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Fr 26.01.07 17:45 
Real-Typen sollten aufgrund der ungenauen Darstellung im Rechner niemals mit = verglichen werden. Du hast in deinem Code eine Funktion IsZero drin. Ich würde mal den Vergleich a=b durch IsZero(a-b,0.000001) ersetzen, dann sollte es gehen.

_________________
We are, we were and will not be.
freedy Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 403
Erhaltene Danke: 1

Winows 7
Delphi XE
BeitragVerfasst: Fr 26.01.07 17:50 
Zitat:
Real-Typen sollten aufgrund der ungenauen Darstellung im Rechner niemals mit = verglichen werden. Du hast in deinem Code eine Funktion IsZero drin. Ich würde mal den Vergleich a=b durch IsZero(a-b,0.000001) ersetzen, dann sollte es gehen.


Schon ausprobiert. Klappt nicht, da b den Wert 0 annimmt, während a näherungsweise 1 ist. IsZero war also keine Lösung.

Die Zeilen, wo a und b "berechnet" werden, sollten ja verständlich sein. Ich prüfe, ob der Log-Wert eine Zahl ohne Nachkommastellen ist.

Kennt da vielleicht noch jemand eine andere Lösung?
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Fr 26.01.07 17:58 
Dann probier mal, ob du mit Frac weiterkommst. Das liefert die Nachkommastellen. Wenn die fast 0 sind, oder 1-frac fast 0, dann bist du sehr nahe an einer ganzen Zahl dran.

_________________
We are, we were and will not be.
freedy Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 403
Erhaltene Danke: 1

Winows 7
Delphi XE
BeitragVerfasst: Fr 26.01.07 18:04 
Das kann nicht funktionieren.

Das Problem sind doch die Nachkommastellen, die Trunc() abschneidet. Das Programm rechnet ja richtig. log(10) ist 1. Jetzt schneide ich von diesem Wert aber die Nachkommastellen ab und weise ihn b zu. Da der Wert aber nicht genau 1 war, ist b = 0. Er rechnet aber mit a = 1 weiter. Natürlich sind die beiden nicht gleich, so dass er logischerweise nicht in meine if-Schleife läuft. Frac() liefert mir leider aber genau 0 zurück.



Edit:

Damit klappt es jetzt doch:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
  //....

  if (frac(log10(I)) = 0or IsZero(1 - frac(log10(I)), 1e-10then
  begin
    TextOut(pix + 2, Image1.Height div 2 + 8, FloatToStr(I));
    Step := I;
  end;

  //....


Gruß


Zuletzt bearbeitet von freedy am Fr 26.01.07 18:10, insgesamt 1-mal bearbeitet
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Fr 26.01.07 18:09 
Deswegen hab ich ja Frac vorgeschlagen. Wenn die Nachkommastellen .0000001 sind oder .999999, dann ist man sehr nahe bei einer ganzen Zahl und geht in die Schleife rein. Oder verstehe ich dich immer noch nicht richtig?

Edit: Hab dein Edit nicht gelesen ;-)

_________________
We are, we were and will not be.
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: So 28.01.07 16:58 
user profile iconfreedy hat folgendes geschrieben:
Das kann nicht funktionieren.

Das Problem sind doch die Nachkommastellen, die Trunc() abschneidet. Das Programm rechnet ja richtig. log(10) ist 1. Jetzt schneide ich von diesem Wert aber die Nachkommastellen ab und weise ihn b zu. Da der Wert aber nicht genau 1 war, ist b = 0. Er rechnet aber mit a = 1 weiter. Natürlich sind die beiden nicht gleich, so dass er logischerweise nicht in meine if-Schleife läuft. Frac() liefert mir leider aber genau 0 zurück.


Es gibt keine If-Schleifen!!!

Zu deinem Problem: Probier mal Round statt Trunc.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
freedy Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 403
Erhaltene Danke: 1

Winows 7
Delphi XE
BeitragVerfasst: Mo 29.01.07 01:23 
user profile iconBenBE hat folgendes geschrieben:


Es gibt keine [url=www.if-schleife.de]If-Schleifen[/url]!!!


Nein, natürlich nicht. "verschrieben"! Soll jetzt keine Ausrede sein. Fehler ist natürlich Fehler. Das "if" habe ich nachträglich zugefügt.

user profile iconBenBE hat folgendes geschrieben:

Zu deinem Problem: Probier mal Round statt Trunc.


Hat sich alles schon erledigt. Mit Round klappte es übrigens gar nicht.

Gruß