Autor |
Beitrag |
freedy
      
Beiträge: 403
Erhaltene Danke: 1
Winows 7
Delphi XE
|
Verfasst: 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):
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 public 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.00000001) then 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
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: 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 
      
Beiträge: 403
Erhaltene Danke: 1
Winows 7
Delphi XE
|
Verfasst: 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
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: 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 
      
Beiträge: 403
Erhaltene Danke: 1
Winows 7
Delphi XE
|
Verfasst: 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:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| if (frac(log10(I)) = 0) or IsZero(1 - frac(log10(I)), 1e-10) then 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
      
Beiträge: 8548
Erhaltene Danke: 477
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: 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
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 28.01.07 16:58
freedy 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 
      
Beiträge: 403
Erhaltene Danke: 1
Winows 7
Delphi XE
|
Verfasst: Mo 29.01.07 01:23
Nein, natürlich nicht. "verschrieben"! Soll jetzt keine Ausrede sein. Fehler ist natürlich Fehler. Das "if" habe ich nachträglich zugefügt.
BenBE hat folgendes geschrieben: |
Zu deinem Problem: Probier mal Round statt Trunc. |
Hat sich alles schon erledigt. Mit Round klappte es übrigens gar nicht.
Gruß
|
|
|