Logarithmus-Problem...

Hier kann alles mögliche diskutiert werden. Themen zu Purebasic sind hier erwünscht.
Flames und Spam kommen ungefragt in den Mülleimer.
Benutzeravatar
ZeHa
Beiträge: 4760
Registriert: 15.09.2004 23:57
Wohnort: Friedrichshafen
Kontaktdaten:

Logarithmus-Problem...

Beitrag von ZeHa »

Servus,

ich hoffe hier kann mir der ein oder andere weiterhelfen :)
Wie läuft das, wenn ich z.B. eine logarithmische Skala habe, z.B. den Frequenzbereich von 0 bis 20 kHz, und diesen nun in einem Koordinatensystem anzeigen will?

Nehmen wir an, ich hätte die ganz normale Logarithmus-Kurve, die ja nach rechts immer flacher wird. Nun will ich die so anzeigen, daß sie exakt diagonal ist, also muß ich ja die x-Achse entsprechend logarithmisch skalieren.

Wie kann ich das am einfachsten umsetzen? Wie muß ich die einzelnen Werte skalieren? Was muß ich beachten? Ist das Vorgehen immer gleich, egal ob meine Werte von 0 bis 10 oder von 0 bis 20000 gehen? Wie gehe ich mit Sonderfällen um (z.B. 0 und 1)?
Bild     Bild

ZeHa hat bisher kein Danke erhalten.
Klicke hier, wenn Du wissen möchtest, woran ihm das vorbeigeht.
Benutzeravatar
ZeHa
Beiträge: 4760
Registriert: 15.09.2004 23:57
Wohnort: Friedrichshafen
Kontaktdaten:

Beitrag von ZeHa »

Ach ja, ich hab schonmal eine Schleife von 0 bis 20000 gemacht, und mir alle Werte mal ausgeben lassen, wenn ich den Zähler in Math.log() einsetze (ich arbeite gerade mit Java, und Math.log() ist der ln).

Diese Werte habe ich dann durch den Maximalwert geteilt (also log(20000)), um nur Werte zwischen 0 und 1 zu kriegen, und diese dann wieder mit 20000 multipliziert. Könnte das evtl. das richtige Vorgehen sein?
Bild     Bild

ZeHa hat bisher kein Danke erhalten.
Klicke hier, wenn Du wissen möchtest, woran ihm das vorbeigeht.
Benutzeravatar
ZeHa
Beiträge: 4760
Registriert: 15.09.2004 23:57
Wohnort: Friedrichshafen
Kontaktdaten:

Beitrag von ZeHa »

Wenn ich mir das ausgebe, sieht die Kurve schonmal nicht soooo schlecht aus, aber ich habe eben das Problem mit dem Sonderfall bei 0 und 1... und wenn ich nur die Range von 2 bis 20000 nehme, kommt mir als Maximalwert nur ca. 18000 raus und nicht die gewünschte 20000...

Und was mich auch stutzig macht ist der seeehr große Sprung zwischen dem ersten und dem zweiten Punkt... das müßte doch weicher gehen, oder?

So sieht die Kurve aus (vertikal):

Code: Alles auswählen

_____________________________________*
_________________*
______________*
_____________*
____________*
___________*
__________*
_________*
_________*
________*
________*
________*
_______*
_______*
_______*
______*
______*
______*
______*
_____*
_____*
_____*
_____*
_____*
____*
____*
____*
____*
____*
____*
___*
___*
___*
___*
___*
___*
___*
___*
___*
__*
__*
__*
__*
__*
__*
__*
__*
__*
__*
_*
_*
_*
_*
_*
_*
_*
_*
_*
_*
_*
_*
_*
_*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*

Und das ist der Code:

Code: Alles auswählen

double max = Math.log(20000);

for(int i=2; i<20001; i+=250)
{
    int val = (int)(40 - (Math.log(i) / max) * 40);
    
    for(int k=0; k<val; k++)
        System.out.print("_");
    
    System.out.println("*");
}
Ich multipliziere jetzt natürlich nur mit 40, damit es gescheit ausgegeben wird. Ist aber nur 'ne Skalierung, von daher unbedeutend...
Bild     Bild

ZeHa hat bisher kein Danke erhalten.
Klicke hier, wenn Du wissen möchtest, woran ihm das vorbeigeht.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

ich bin etwas verwirrt, was willst du ? ^^

wenn du zB die 2^x Funktion nimmst, und diese auf einfach Logerithmischen Papier aufträgst wird aus der Hyperbeleine Gerade.

Die Einteilung der Achse ist dann nicht in gleichen Abständen :
1, 2, 3, 4, 5...
sondern halt 1,10,100,1000,10000...
damit du weiß wo du nun zB 5 abstägt (was ja nicht genau bei der hälfe zwischen 1 und 10 ist) rechnest du einfach mal kurz LOG10(5) und erhälst 0,698

Das heißt wenn 1 bei 0cm ist und 10 bei 10cm ist 5 bei 7cm.

Hier mal n Beispiel:
Bild
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
ZeHa
Beiträge: 4760
Registriert: 15.09.2004 23:57
Wohnort: Friedrichshafen
Kontaktdaten:

Beitrag von ZeHa »

Also ich formulier es mal ein bißchen anders...

Sagen wir, ich hab ein Array mit 20000 Zahlen, und all diese Zahlen bilden im Endeffekt eine Kurve. Wenn ich diese nun auf dem Bildschirm darstellen möchte, in einer Breite von z.B. 400 Pixeln, dann muß ich einfach nur jeden 50. Wert rauspicken und auf dem Bildschirm darstellen.

Nun möchte ich diese Kurve aber nicht linear, sondern logarithmisch anzeigen, also kann ich nicht einfach jeden 50. Wert nehmen, sondern anfangs muß ich kleinere Schritte machen und am Ende sehr große. Klar soweit? Wenn nicht, bitte diesen Absatz nochmal lesen :)

Im Endeffekt will ich also die Indizes ausrechnen, die ich brauche, um die einzelnen Werte aus meinem Array zu kriegen, die ich anzeigen muß, damit meine Kurve logarithmisch angezeigt wird.



Vielleicht ist es durch dieses Beispiel etwas klarer geworden...
Bild     Bild

ZeHa hat bisher kein Danke erhalten.
Klicke hier, wenn Du wissen möchtest, woran ihm das vorbeigeht.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

Du verstehst das falsch, du musst nicht die Definitions-Achse neu Skalieren sondern die Werte-Achse.

Das heißt das du von allen werten im Array einfach den LOG() bildest und dnan aber trotzdem jede 50. Zahlen anzeigst
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Froggerprogger
Badmin
Beiträge: 855
Registriert: 08.09.2004 20:02

Beitrag von Froggerprogger »

Man kann jede Achse logarithmisch stauchen. Für die x-Achse hier ein Beispiel:
Um linear aus 20000 Elementen (mit Indizes 0..19999) 400 auszuwählen nimmt man ja einfach jedes 20000/400-ste Element, also 0, 50, 100, 150,....

Um logarithmisch gestaucht auszuwählen, kann man linear im Exponenten mappen. Dazu muss man zunächst neue minimale/maximale Grenzen für den Exponenten definieren z.B. per expMin = 0 und expMax = log10(20000). So kann man nun den minimalen Wert 0 darstellen als 0=10^expMin - 1 und den maximalen Wert als 19999=10^expMax - 1. Um jetzt z.B. 400 daraus auszuwählen, mappt man linear zwischen expMin und expMax und erhält den Wert 'exp'. Den zugehörige Index erhält man über 10^exp - 1, wobei man 'echt' runden sollte. Hier ein Beispiel:
#Size = 20000

; prepare array
Dim A.f(#Size)
For i=0 To #Size-1
A(i) = Log(1+i)
Next

; transform linear mapped indices between 0 and #Size-1 to
; float-indices inside 0 and log(#Size-1) for logarithmic mapping to base 10
; so it is 0 = 10^expMin-1 and #Size-1 = 10^expMax-1
expMin.f = 0
expMax.f = Log10(#Size)

Debug expMax
Debug Pow(10, expMax)

#W = 20
For i=0 To #W-1
; now map 'exp' linear between expMin and expMax to get the index 10^exp - 1 (rounded)
exp.f = (i * (expMax - expMin)) / (#W-1)
index = Pow(10, exp) - 1 ; should be done with additional real round

Debug index
Next
Die Werteachse logarithmisch zu stauchen ist so einfach wie von Stargate beschrieben.
Zuletzt geändert von Froggerprogger am 14.03.2008 17:00, insgesamt 2-mal geändert.
!UD2
Benutzeravatar
ZeHa
Beiträge: 4760
Registriert: 15.09.2004 23:57
Wohnort: Friedrichshafen
Kontaktdaten:

Beitrag von ZeHa »

Okay, vielen Dank schonmal, ich werde mir allerdings nochmal etwas überlegen und morgen schreiben, weil ich hab das Problem daß ich nur sehr schwer erklären kann wo meine Verständnisprobleme liegen. Dennoch, ich glaube die Lösung von Frofferproffer ist ungefähr auch das, was ich machen wollte... aber wie gesagt, ich schreib morgen nochmal genaueres :)

EDIT: Wie peinlich... hab mich vertippt... sollte natürlich Froggerprogger heißen und nicht Frofferproffer ;)

Die genaueren Ausführungen kommen noch... hab im Moment grad ein anderes Problem das mehr Priorität hat...
Bild     Bild

ZeHa hat bisher kein Danke erhalten.
Klicke hier, wenn Du wissen möchtest, woran ihm das vorbeigeht.
Sebe
Beiträge: 585
Registriert: 11.09.2004 21:57
Wohnort: Europa
Kontaktdaten:

Beitrag von Sebe »

Das ist der Logarithmus bei dem jeder mit muss :freak:
Benutzeravatar
ZeHa
Beiträge: 4760
Registriert: 15.09.2004 23:57
Wohnort: Friedrichshafen
Kontaktdaten:

Beitrag von ZeHa »

Hmm okay, also mir ging es eigentlich um beides, also sowohl um die x- als auch um die y-Achse, je nach Anwendungszweck also.

Für die x-Achse muß ich also das von Froggerprogger machen, und für die y-Achse das was Stargate sagt, richtig?

Was ich nun nicht ganz verstehe: nehmen wir an ich will die y-Achse stauchen, und ich nehme von jedem Wert, den ich darauf anzeige, einfach den Log-Wert. Dann habe ich keine Ahnung, in welcher Größenordnung sich die Werte befinden werden. Wenn ich das nun auf Werte zwischen 0 und 1 skalieren will, durch welchen Wert muß ich dann teilen? Ich würde jetzt halt den maximalen y-Wert nehmen, davon den Log, und dann durch diesen alle teilen, dann müßten ja alle zwischen 0 und 1 liegen. Oder muß ich das ebenfalls wie bei Froggerproggers Methode machen?

Und was mache ich eben mit den Sonderfällen 0 und 1? Der Log von 0 ist ja -Unendlich...
Oder erübrigt sich das bei Froggerproggers Methode sowieso?
Bild     Bild

ZeHa hat bisher kein Danke erhalten.
Klicke hier, wenn Du wissen möchtest, woran ihm das vorbeigeht.
Antworten