Deutsch
Wünsche und Anregungen

Wunsch: Frac als XProfanfunktion

 
[quote:00a30dd46d=Michael Wodrich]Ich wußte doch, daß ich das direkte Zugreifen auf Double-Werte von Profan schon mal rausgetüftelt hatte....

Damit habe ich die Funktion FindEdge() etwas direkter programmiert. Diese Funktion ist im Original unter den Beispielen als Fließkommazahlen.prf zu finden.

Außerdem habe ich mich mal an dem Gegenstück zu INT() versucht. Unter Pascal heißt diese Funktion Frac().

Dieser Codeschnipsel ist noch mit der MemoryModule-freien Version von XPIA getestet worden - läuft bei mir fehlerfrei.

Da fällt mir ein: wird es in XPIA einstellbar sein, welche Variante man einsetzt?
Das Generieren einer externen DLL hat ja auch seine Vorteile - z.B. für ältere Profan-Versionen eine DLL zu erstellen.

Hier der Code:
KompilierenMarkierenSeparieren
!
 {$cleq}
 {$cliq}

Proc geaendertes_Beispiel

    Sucht die höchste und die niedrigste Zahl aus einem Array mit Fließkommazahlen.
    Declare anzahl&
    Anzahl Fließkommazahlen im Array
    anzahl& = 30
    Declare Tabelle_1![anzahl&], Tabelle_2![2], x&, y&, z&, text$
    Randomize
    Zufällige Fließkommazahlen
    generieren.

    WhileLoop anzahl&

        Tabelle_1![&loop - 1] = Rnd(100000) / 1.09 - 50000

    EndWhile

    Assemblerfunktions-Parameters:  Adresse von Tabelle mit Floats, Adresse von Zieltabelle, Anzahl Floats

    AsmStart FindEdge ( addr(Tabelle_1![0]), addr(Tabelle_2![0]), anzahl& )

        Local  tmp :REAL10
        mov    edx, para1
        mov    ebx, para2
        mov    ecx, para3
        fld    qword ptr [edx]        ; st(3): min   STK:(0:min)
        fld    qword ptr [edx]        ; st(2): max   STK:(0:max,1:min)
        schleife:
        fld    qword ptr [edx]        ; st(1): akt. Vergleichswert   STK:(0:akt,1:max,2:min)
        fld    st(0)                  ; st(0)  dupl. akt. Vergleichswert   STK:(0:akt,1:akt,2:max,3:min)
        fcomp  st(3)                  ; cmp st0 < st3 ? (st0 wird geändert/entfernt)   STK:(0:akt,1:max,2:min)
        fnstsw ax
        sahf
        jae    over1                  ; überspringe wenn st0 >= st3
        fst    st(2)                  ; sichere neuen Minimumwert (derzeit st2)   STK:(0:akt,1:max,2:neumin)
        over1:
        fld    st(0)                  ; st(0)  dupl. akt. Vergleichswert   STK:(0:akt,1:akt,2:max,3:min)
        fcomp  st(2)                  ; cmp st0 > st2 ? (st0 wird geändert/entfernt)   STK:(0:akt,1:max,2:min)
        fnstsw ax
        sahf
        jbe    over2                  ; überspringe wenn st0 <= st2
        fst    st(1)                  ; sichere neuen Maximumwert (derzeit st1)   STK:(0:akt,1:neumax,2:min)
        over2:
        fstp   [tmp]                  ; entferne akt.Wert vom Stapel   STK:(0:max,1:min)
        add    edx, 8						; auf den nächsten double-Wert zeigen
        sub    ecx, 1                 ; Countdown
        jne    schleife               ; solange <> 0 : weitermachen
        fstp   qword ptr [ebx]        ; Maximum sichern   STK:(0:min)
        fstp   qword ptr [ebx+8]      ; Minimum sichern   STK:()

    AsmEnd

    --- kleiner Zusatz-Programmteil ---
    Zahlen am Dezimalpunkt ausrichten
    - zuerst den am weitesten rechts stehenden Dezimalpunkt feststellen
    Declare Dezipunkt%, i%,tmp$, j%,tmp2$

    WhileLoop anzahl&

        tmp$ = Str$(Tabelle_1![&loop - 1])
        i% = InStr(".",tmp$)
        Case (i% = 0) : i% = Len(tmp$) + 1  dann stehen Integers vor dem Dezipunkt
        Case (i% > Dezipunkt%) : Dezipunkt% = i%

    EndWhile

    Inc Dezipunkt%  dadurch ist links mind. ein Leerzeichen
    - dann die ausgerichtete Ausgabe

    WhileLoop anzahl&

        tmp$ = Str$(Tabelle_1![&loop - 1])
        i% = InStr(".",tmp$)

        If i% = 0

            Print Space$(Dezipunkt% - Len(tmp$) - 1) + tmp$

        Else

            Print Space$(Dezipunkt% - i%) + tmp$

        EndIf

    EndWhile

    - für die MinMax-Werte
    tmp$ = Str$(Tabelle_2![0])
    i% = InStr(".",tmp$)
    tmp2$ = Str$(Tabelle_2![1])
    j% = InStr(".",tmp2$)
    Dezipunkt% = if(i% > j%,i%,j%) + 1
    Print
    Print "Höchste Zahl aus dem Array    =", Space$(Dezipunkt% - i%) + tmp$
    Print "Niedrigste Zahl aus den Array =", Space$(Dezipunkt% - j%) + tmp2$

EndProc

Proc Frac

    Parameters value!

    AsmStart Frac_asm ( Addr(value!) )

        Local d1 :WORD
        local d2:word
        mov     edx, para1
        fnstcw  [d1]		; fpu control word wegsichern
        fwait			; warten
        mov     cx, [d1]
        or      cx, 0F00h		; Präzision/Rundung maskieren (keine Rundung)
        mov     [d2], cx		; Änderung nach d2
        fldcw   [d2]		; ...und in die fpu
        fld     qword ptr [edx]	; Wert laden
        frndint			; runde Wert auf Ganzzahl (also abschneiden)
        fld     qword ptr [edx]	; Wert laden (st0=gesamtwert,st1=INT-Wert)
        fsub    st(0), st(1)		; value! - INT(value!)
        fstp    st(1)		; st0 nach st1 kopieren und st0 vom stack entfernen
        fstp    qword ptr [edx]	; jetzigen st0 nach value! speichern
        fldcw   [d1]		; fpu control word zurückladen

    AsmEnd

    Return value!

EndProc

Proc Ausgabe

    Parameters d!
    print "Wert.....: ", d!
    print "gerundet.: ", Round( d!, 0 )
    print "Ganzzahl.: ", Int( d! )
    print "Nachkomma: ", Frac( d! )

EndProc

--- Main ---
set("decimals",15)
WindowTitle "Frac - anschließend geändertes Fließkommazahlen.prf"
Window 0,0 - %maxx,%maxy
Print
Print "Zeigt das Runden, den Vorkomma-Wert, und mittels Assembler den Nachkomma-Wert."
Print
Print "----------"
Ausgabe 5.6
Print "----------"
Ausgabe Pi()
Print "----------"
Print
Print "weiter mit Tastendruck/Mausklick"
Print
waitinput
WindowTitle "jetzt geändertes Fließkommazahlen.prf"
geaendertes_Beispiel
Print
Print "Dieses FindEdge findet Maximum und Minimum"
Print "in einem Array in nur einem Durchgang."
Print "Zur Zwischenspeicherung wird der FPU-Stack benutzt."
Print
Print "Zahlen werden am Dezimalpunkt ausgerichtet."
Print
Print "Ende nach Tastendruck/Mausklick"
waitinput
end

Schöne Grüße
Michael Wodrich[/quote:00a30dd46d]
 
09.01.2007  
 



Antworten


Thementitel, max. 100 Zeichen.
 

Systemprofile:

Kein Systemprofil angelegt. [anlegen]

XProfan:

 Beitrag  Schrift  Smilies  ▼ 

Bitte anmelden um einen Beitrag zu verfassen.
 

Themenoptionen

1.569 Betrachtungen

Unbenanntvor 0 min.
Michael W.31.10.2014
Thomas Freier31.12.2013
p.specht31.12.2013

Themeninformationen

Dieses Thema hat 1 Teilnehmer:

iF (1x)


Admins  |  AGB  |  Anwendungen  |  Autoren  |  Chat  |  Datenschutz  |  Download  |  Eingangshalle  |  Hilfe  |  Händlerportal  |  Impressum  |  Mart  |  Schnittstellen  |  SDK  |  Services  |  Spiele  |  Suche  |  Support

Ein Projekt aller XProfaner, die es gibt!


Mein XProfan
Private Nachrichten
Eigenes Ablageforum
Themen-Merkliste
Eigene Beiträge
Eigene Themen
Zwischenablage
Abmelden
 Deutsch English Français Español Italia
Übersetzungen

Datenschutz


Wir verwenden Cookies nur als Session-Cookies wegen der technischen Notwendigkeit und bei uns gibt es keine Cookies von Drittanbietern.

Wenn du hier auf unsere Webseite klickst oder navigierst, stimmst du unserer Erfassung von Informationen in unseren Cookies auf XProfan.Net zu.

Weitere Informationen zu unseren Cookies und dazu, wie du die Kontrolle darüber behältst, findest du in unserer nachfolgenden Datenschutzerklärung.


einverstandenDatenschutzerklärung
Ich möchte keinen Cookie