Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Logarithmus Log zu Delphi (https://www.delphipraxis.net/200099-logarithmus-log-zu-delphi.html)

EWeiss 20. Mär 2019 06:00

Logarithmus Log zu Delphi
 
Habe leider immer wieder Geleitkommaüberläufe.

Der Ausgang..

Code:
b ist Long..
b = (Log(Sqr(Spectrum(i1).r * Spectrum(i1).r + Spectrum(i1).i * Spectrum(i1).i) + 0.0001) + 9.21034037197618) * q1
das ganze nach Delphi
Delphi-Quellcode:
b: Single;
b := (LN(Sqr(Spectrum[i1].r * Spectrum[i1].r + Spectrum[i1].i * Spectrum[i1].i) + 0.0001) + 9.21034037197618) * q1;
bin mir aber nicht sicher ob LN der richtige Datentyp ist.

Alternativen Wenn nicht?
Keine Ahnung wie ich die Ergebnisse wenn -NAN, +NAN abfangen soll.
Ungültige Gleitkomma Operationen. grrr...

Muss dabei sagen das ich kein Mathe experte bin..

gruss

Jasocul 20. Mär 2019 06:28

AW: Logarithmus Log zu Delphi
 
Ich habe Delphi noch nicht gestartet, aber ist das Ergebnis nicht vom Typ Extended?

hoika 20. Mär 2019 06:36

AW: Logarithmus Log zu Delphi
 
Hallo,
Zitat:

Keine Ahnung wie ich die Ergebnisse wenn -NAN, +NAN abfangen soll.
Da kann man doch so ein 8087-Flag (https://www.oreilly.com/library/view...595/re288.html) setzen oder try except ;)

EWeiss 20. Mär 2019 06:45

AW: Logarithmus Log zu Delphi
 
Zitat:

Zitat von hoika (Beitrag 1428121)
Hallo,
Zitat:

Keine Ahnung wie ich die Ergebnisse wenn -NAN, +NAN abfangen soll.
Da kann man doch so ein 8087-Flag (https://www.oreilly.com/library/view...595/re288.html) setzen oder try except ;)

Delphi-Quellcode:
constructor TSpectrum.Create;
begin
//  Saved8087CW := Default8087CW;
//  Set8087CW($133f);

  FFFTSize := 2048;
  FFTLog := 11;
end;
es nutzt nur nichts deshalb wieder aus kommentiert.
try except auch nicht!

sobald ich hier abfrage

Delphi-Quellcode:
b := (LN(Sqr(Spectrum[i1].r * Spectrum[i1].r + Spectrum[i1].i * Spectrum[i1].i) + 0.0001) + 9.21034037197618) * q1;


und die Rückgabe +NAN oder -NAN ist dann kracht es.

gruss

Klaus01 20. Mär 2019 07:04

AW: Logarithmus Log zu Delphi
 
sqr in Visual basic -> Square root , also Quadrat Wurzel

sqr in Delphi -> Square -> Quadratzahl

sqrt in Delphi -> Square root

Quelle: http://www.vbforums.com/showthread.p...9-Sqr-And-Sqrt

Grüße
Klaus

EWeiss 20. Mär 2019 07:29

AW: Logarithmus Log zu Delphi
 
Zitat:

Zitat von Klaus01 (Beitrag 1428123)
sqr in Visual basic -> Square root , also Quadrat Wurzel

sqr in Delphi -> Square -> Quadratzahl

sqrt in Delphi -> Square root

Quelle: http://www.vbforums.com/showthread.p...9-Sqr-And-Sqrt

Grüße
Klaus

Ahhh dann ist sqr definitiv schon mal falsch.
Was ist mit LN?

Danke!

gruss

Sherlock 20. Mär 2019 07:36

AW: Logarithmus Log zu Delphi
 
Welcher Logarithmus ist hier erwünscht? Das Log im VB-Beispiel ist gemäß Doku der natürliche (also Basis e). Der Delphi Log ist der dekadische (Basis 10). Korrekt wäre System.Ln.

Sherlock

Klaus01 20. Mär 2019 07:36

AW: Logarithmus Log zu Delphi
 
Zitat:

Zitat von EWeiss (Beitrag 1428124)
Was ist mit LN?

Danke!

gruss

..sollte passen.

https://docs.microsoft.com/en-us/dot...ystem.math.log

In Delphi code, Ln returns the natural logarithm (Ln(e) = 1) of the real-type expression X.



Grüße
Klaus

EWeiss 20. Mär 2019 07:40

AW: Logarithmus Log zu Delphi
 
Zitat:

Zitat von Sherlock (Beitrag 1428125)
Welcher Logarithmus ist hier erwünscht? Das Log im VB-Beispiel ist gemäß Doku der natürliche (also Basis e). Der Delphi Log ist der dekadische (Basis 10). Korrekt wäre System.Ln.

Sherlock

Jo und den verwende ich System.LN. Danke.
Leider habe ich trotzdem das Problem mit -NAN obwohl ich schon den Überlauf prüfe.

Delphi-Quellcode:
 function LimitedSingleValue(doubleVal: double): single;
 begin
   if doubleVal > MaxSingle then
     result := MaxSingle
   else if doubleVal < MinSingle then
     result := MinSingle
   else
     result := doubleVal;
 end;
Schlage mich damit jetzt schon ein paar Tage mit rum. ;)
Also wenn an doubleVal der wert -NAN ankommt dann kracht es trotzdem.

Zitat:

..sollte passen.
Danke Klaus.

gruss

Klaus01 20. Mär 2019 07:54

AW: Logarithmus Log zu Delphi
 
.. du könntest zusätzlich auf isNAN testen.

Grüße
Klaus

Sherlock 20. Mär 2019 07:56

AW: Logarithmus Log zu Delphi
 
Eventuell führst Du nicht alles in einem Schritt durch, sondern ziehst erst die Wurzel und schaust, ob da ein "ln-taugliches" Ergebnis raus kommt (zumindest mal positiv).

Sherlock

EWeiss 20. Mär 2019 07:59

AW: Logarithmus Log zu Delphi
 
Zitat:

Zitat von Klaus01 (Beitrag 1428129)
.. du könntest zusätzlich auf isNAN testen.

Grüße
Klaus

Das habe ich schon versucht.
Zitat:

Eventuell führst Du nicht alles in einem Schritt durch, sondern ziehst erst die Wurzel und schaust, ob da ein "ln-taugliches" Ergebnis raus kommt (zumindest mal positiv).
Hier ist mal der Algo..

Delphi-Quellcode:
procedure TSpectrum.FFT(Dat: array of TComplex);
var
  i, j, n, K , io, ie, in_, nn: Integer;
  u, tp, tq, w: TComplex;
  sr, mGain: Single;

 function LimitedSingleValue(doubleVal: double): single;
 begin
   if doubleVal > MaxSingle then
     result := MaxSingle
   else if doubleVal < MinSingle then
     result := MinSingle
   else
     result := doubleVal;
 end;

begin

  if not FFTInit then
  begin
    InitFFT;
    FFTInit := True;
  end;

  nn := FFFTSize div 2;
  ie := FFFTSize;
  for n := 1 to FFTLog do
  begin
    w := Coef[FFTLog - n];
    in_ := ie div 2;
    u.r := 1;
    u.i := 0;

    for j := 0 to (in_ - 1) do
    begin
      for i := j to (FFFTSize - 1) do
      begin
        if i mod ie <> 0 then
          continue;

        io := i + in_;

        if (i >= (FFFTSize - 1)) or (io >= (FFFTSize - 1)) then
          continue;

        tp.r := LimitedSingleValue(Dat[i].r + Dat[io].r);
        tp.i := LimitedSingleValue(Dat[i].i + Dat[io].i);

        tq.r := Dat[i].r - Dat[io].r;
        tq.i := Dat[i].i - Dat[io].i;

        Dat[io].r := tq.r * u.r - tq.i * u.i;
        Dat[io].i := LimitedSingleValue(tq.i * u.r + tq.r * u.i);
        Dat[i] := tp;
      end;
      sr := u.r;
      u.r := u.r * w.r - u.i * w.i;
      u.i := u.i * w.r + sr * w.i;
    end;
    ie := ie div 2;
  end;

  j := 1;
  for i := 1 to (FFFTSize - 1) do
  begin
    if i < j then
    begin
      io := i - 1;
      in_ := j - 1;
      tp := Dat[in_];
      Dat[in_] := Dat[io];
      Dat[io] := tp;
    end;

    K := nn;
    While K < j do
    begin
      j := j - K;
      K := K div 2;
    end;
    j := j + K;
  end;

  mGain := (FGain / 100);
  if FView = 0 then
    sr := (4096 * mGain) / FFFTSize
  else
  sr := 1 / FFFTSize;

  for i := 0 to (FFFTSize div 2) - 1 do
  begin
    Dat[i].r := Dat[i].r * sr;
    Dat[i].i := Dat[i].i * sr;
  end;
end;
gruss

Klaus01 20. Mär 2019 08:01

AW: Logarithmus Log zu Delphi
 
Zitat:

Zitat von Sherlock (Beitrag 1428130)
Eventuell führst Du nicht alles in einem Schritt durch, sondern ziehst erst die Wurzel und schaust, ob da ein "ln-taugliches" Ergebnis raus kommt (zumindest mal positiv).

Sherlock

Delphi-Quellcode:
b := (LN(Sqrt(sqr(Spectrum[i1].r) + sqr(Spectrum[i1].i)) + 0.0001) + 9.21034037197618) * q1;

In Prinzip kann das ganze nur negativ werden wenn q1 < 0 ist.
LN bekommt immer ein positiven Wert gebildet aus: sqrt(sqr(Spectrum[i1].r) + sqr(Spectrum[i1].i)) + 0.0001

Grüße
Klaus

EWeiss 20. Mär 2019 08:04

AW: Logarithmus Log zu Delphi
 
Zitat:

Zitat von Klaus01 (Beitrag 1428132)
Zitat:

Zitat von Sherlock (Beitrag 1428130)
Eventuell führst Du nicht alles in einem Schritt durch, sondern ziehst erst die Wurzel und schaust, ob da ein "ln-taugliches" Ergebnis raus kommt (zumindest mal positiv).

Sherlock

Delphi-Quellcode:
b := (LN(Sqrt(sqr(Spectrum[i1].r) + sqr(Spectrum[i1].i)) + 0.0001) + 9.21034037197618) * q1;
In Prinzip kann das ganze nur negativ werden wenn q1 < 0 ist.

Grüße
Klaus

q1 kann keinen negativen wert bekommen.

Delphi-Quellcode:
  i1 := 1;
  q2 := 0;
  q1 := 0;

  case View of

    0:
      begin
        for o := 0 to FOctaveCount - 1 do
        begin
          fl := True;
          q2 := q2 + OctAreaSize;

          i2 := i1 * 2;
          While i1 < i2 do
          begin
            b := round(Sqrt(Spectrum[i1].r * Spectrum[i1].r + Spectrum[i1].i * Spectrum[i1].i));
            if b > 255 then
              b := 255;

            GDIP_SetPenColor(Pen, Palette[round(b)]);

            if MapData[i1].IsLine then
            begin
              if not fl then
              begin
                GDIP_SetPenWidth(Pen, 1);

                fl := True;
                q1 := q1 + 4;
                q2 := q2 + 2;

               GDIP_DrawLine(grSpectrum, Pen, MapData[i1].fa * q1 + Sw,
                 MapData[i1].ta * q1 + Sh, MapData[i1].fa * q2 + Sw,
                 MapData[i1].ta * q2 + Sh);
              end;
            end else
              begin
                if fl then
                begin
                  GDIP_SetPenWidth(Pen, OctAreaSize - 2);
                  fl := False;

                  GDIP_DrawArc(grSpectrum, Pen, Sw - q2, Sh - q2, q2 * 2 - 1, q2 * 2 - 1,
                    MapData[i1].fa, MapData[i1].ta);
                end;
              end;
              i1 := i1 + 1;
          end;
          q1 := q1 + OctAreaSize;
        end;
      end;
gruss

Sherlock 20. Mär 2019 08:09

AW: Logarithmus Log zu Delphi
 
Stimmt, und das ist nach dem ln.

Also muß man prüfen, ob da Extremwerte rauskommen, die der ln nicht verkraftet. Leider ist die Doku da sehr dünn, und ich habe vom ln an sich zu wenig Ahnung.

Sherlock

Klaus01 20. Mär 2019 08:21

AW: Logarithmus Log zu Delphi
 
.. wie groß können denn Spectrum[i1].r und Spectrum[i1].i maximal werden?

wenn die gegen 0 gehen wird der ln von .0001 gebildet -> -9.2103403719761827360719658187375

Grüße
Klaus

EWeiss 20. Mär 2019 08:28

AW: Logarithmus Log zu Delphi
 
Zitat:

Zitat von Sherlock (Beitrag 1428134)
Stimmt, und das ist nach dem ln.
und ich habe vom ln an sich zu wenig Ahnung.

Sherlock

Mir geht's genauso..
Fand das Original nicht schlecht und wollte es halt mal nach Delphi umsetzen (Nebenbei Vaporware ist das nicht) zu viel Aufwand wie man sehen kann.
Und man kann von lernen. ;)

Mein Hauptproblem zur zeit ist das der Linker mich einfach rausschmeißt.
Delphi-Quellcode:
procedure TSpectrum.FFT(Dat: array of TComplex);
var
  i, j, n, K , io, ie, in_, nn: Integer;
  u, tp, tq, w: TComplex;
  sr, mGain: Single;

 function LimitedSingleValue(doubleVal: double): single; stdcall;
 begin
   if doubleVal > MaxSingle then
     result := MaxSingle
   else if doubleVal < MinSingle then
     result := MinSingle
   else
     result := doubleVal;
 end;

begin

Der linker entfernt variablen.
Delphi-Quellcode:
  mGain := (FGain / 100);
  if FView = 0 then
    sr := (4096 * mGain) / FFFTSize
  else
  sr := 1 / FFFTSize;
hier FFFTSize.

EurekaLog springt dann mit einem Access Violation auf das letzte end im oberen Quelltext. Mit der Meldung vom Speicher kann nicht gelesen werden.
Da ist einiges im argen.

Zitat:

.. wie groß können denn Spectrum[i1].r und Spectrum[i1].i maximal werden?
Kann ich leider mit Bestimmtheit nicht sagen.

Wenn Interesse besteht kann ich den Quelltext zum debuggen aber gerne mal hochladen.
Oder ich schicke einen Link per PN.

gruss

Delphi.Narium 20. Mär 2019 08:42

AW: Logarithmus Log zu Delphi
 
Nur 'ne blöde Idee, ein Schuss ins Blaue:

Mach' bitte mal aus
Delphi-Quellcode:
  mGain := (FGain / 100);
  if FView = 0 then
    sr := (4096 * mGain) / FFFTSize
  else
  sr := 1 / FFFTSize;
dashier:
Delphi-Quellcode:
  mGain := (FGain / 100);
  sr := IfThen(FView = 0, 4096 * mGain, 1) / FFFTSize;
Geht das und ändert sich dann was?

EWeiss 20. Mär 2019 08:50

AW: Logarithmus Log zu Delphi
 
Delphi-Quellcode:
IfThen(FView = 0, (4096 * mGain) / FFFTSize, 1);


Ist am ende das gleiche oder?

Das Ergebnis ist das gleiche.
Habe es versucht. Danke.

gruss

Delphi.Narium 20. Mär 2019 08:58

AW: Logarithmus Log zu Delphi
 
nicht ganz:
entweder
Delphi-Quellcode:
IfThen(FView = 0, (4096 * mGain) / FFFTSize, 1 / FFFTSize);

oder
Delphi-Quellcode:
IfThen(FView = 0, (4096 * mGain), 1) / FFFTSize;


Im ursprünglichen Quelltext findet für sr ja auch im Else noch eine Division durch FFFTSize statt, muss also im IfThen entweder in beiden Fällen durchgeführt werden oder auf das Ergebnis von IfThen.

EWeiss 20. Mär 2019 09:09

AW: Logarithmus Log zu Delphi
 
Delphi-Quellcode:
IfThen(FView = 0, (4096 * mGain), 1) / FFFTSize;

Sorry aber das funktioniert nicht weil IFThen so nicht ausgelegt ist.
Zitat:

[DCC Error] uSpectrum.pas(512): E2014 Statement expected, but expression of type 'Extended' found
Deshalb hatte ich meine Zeile angepasst.

gruss

Delphi.Narium 20. Mär 2019 09:20

AW: Logarithmus Log zu Delphi
 
Ok, dann gibt es keine überladene Version von IfThen für den passenden Datentypen. Schade.

Michael II 20. Mär 2019 09:53

AW: Logarithmus Log zu Delphi
 
Was passiert, wenn du deine Formel

Delphi-Quellcode:
  c := 0.0001;
  d := -ln(c);
...
  b2 := (ln(Sqrt(r * r + i * i) + c ) + d ) * q1;
Schritt für Schritt auswertest?

Also so:
Delphi-Quellcode:
  c := 0.0001;
  d := -ln(c);
...
  b := Sqrt(r * r + i * i);
  b := ln( b + c );
  b := b + d;
  b := b*q1;

Wo haut's dich da raus?


Nebenbei:
Wenn du statt d := 9.21034037197618; (als single Wert speichert Delphi 9.21034049987793) d := -ln(0.0001); verwendest, dann wird b oben für r=i=0 wie gewünscht 0 [auch wenn du dich später für "double" entscheiden solltest].

Man darf es Resultatkosmetik nennen... :)

EWeiss 20. Mär 2019 10:07

AW: Logarithmus Log zu Delphi
 
Zitat:

Was passiert, wenn du deine Formel
Wird wohl das beste sein um den punkt für das Problem zu analysieren.
Danke für die Info.

Das nachträglich zurücksetzen ist kein Problem wenn es dann läuft.

Zitat:

Wenn du statt d := 9.21034037197618
Diese Änderung kann ich vornehmen wenn die Grund Probleme beseitigt sind.. also die abstürze.

gruss

Michael II 20. Mär 2019 11:37

AW: Logarithmus Log zu Delphi
 
Step by Step solltest du rasch sehen, wo's daneben geht.


...und...
d := -ln(0.0001) und deine Konstante 9.21034037197618 (wird gespeichert als 9.21034049987793) sind - solange du alle drei als Single verwendest - gleich.
Der Absturz rührt also sicher nicht daher.
d := -ln(0.0001) spiegelt einfach den "Sinn" der Formel wieder: ¦Spektrum=0¦ muss Nullstelle sein von b(Spektrum,q1).

EWeiss 20. Mär 2019 17:43

AW: Logarithmus Log zu Delphi
 
Zitat:

Zitat von Michael II (Beitrag 1428158)
Step by Step solltest du rasch sehen, wo's daneben geht.


...und...
d := -ln(0.0001) und deine Konstante 9.21034037197618 (wird gespeichert als 9.21034049987793) sind - solange du alle drei als Single verwendest - gleich.
Der Absturz rührt also sicher nicht daher.
d := -ln(0.0001) spiegelt einfach den "Sinn" der Formel wieder: ¦Spektrum=0¦ muss Nullstelle sein von b(Spektrum,q1).

Deaktiviere ich den ganzen Kram
case 0 für die Kreis Visualisierung dann startet die Anwendung aber wird nix visualisiert.

Irgendwo da liegt der Fehler für den Kreis bei case 1 das gleiche.
Muss mich da durch steppen.

PS:
Eigentlich müsste b = 0 sein wenn kein Sound wieder gegeben wird ist aber bei weitem höher.

gruss

Michael II 20. Mär 2019 22:10

AW: Logarithmus Log zu Delphi
 
Ja dann hast du irgendwo sonst ein Problem in deinem Code. Denn b

Delphi-Quellcode:
c := 0.0001;
d := -ln(c);
b := (ln(Sqrt(r * r + i * i) + c ) + d ) * q1;
ist ja genau so gebaut, dass b=0 für ¦Spektrum¦=sqrt(r*r+i*i)=0.

¦Spektrum¦=0 in b eingesetzt:

b = (ln(0+c) - ln(c))*q1 = 0*q1 = 0

EWeiss 20. Mär 2019 22:14

AW: Logarithmus Log zu Delphi
 
Zitat:

Zitat von Michael II (Beitrag 1428209)
Ja dann hast du irgendwo sonst ein Problem in deinem Code. Denn b

Delphi-Quellcode:
c := 0.0001;
d := -ln(c);
b := (ln(Sqrt(r * r + i * i) + c ) + d ) * q1;
ist ja genau so gebaut, dass b=0 für ¦Spektrum¦=sqrt(r*r+i*i)=0.

¦Spektrum¦=0 in b eingesetzt:

b = (ln(0+c) - ln(c))*q1 = 0*q1 = 0

Wenn ich deine Änderungen verwende also Zeile für Zeile die Funktion debuggen will.
Bekomme ich einen Stacküberlauf.
Ich glaube das Teil ist einfach zu hoch für mich. (Mir fehlt die höhere Mathematik um die Probleme lösen zu können)

Edit
wurde zur Seite gelegt im Moment keinen Bock mehr.
Danke für die Hilfe.

gruss


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:37 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz