SQL Funktion Round in PB umwandeln

Anfängerfragen zum Programmieren mit PureBasic.
TheSaint
Beiträge: 143
Registriert: 21.12.2008 18:59

SQL Funktion Round in PB umwandeln

Beitrag von TheSaint »

Hallo Zusammen,

leider krieg ich es irgendwie nicht hin, dieseFunktion, die ich in einem Access Modul nutze, in PB umzuwandeln:

Code: Alles auswählen

Function fctRound(varNr As Variant, Optional varPl As Integer = 2) As Double

'by Konrad Marfurt + ("" by) Luke Chung + Karl Donaubauer
'raus hier bei nicht-nummerischem Argument
    
If Not IsNumeric(varNr) Then Exit Function
        
  fctRound = Fix("" & varNr * (10 ^ varPl) + Sgn(varNr) * 0.5) / (10 ^ varPl)

End Function
Wäre toll, wenn jemand mal draufschauen könnte und mir Hilfestellung geben könnte.
Habe schon nachgesehen nach dem PB - Befehl Round. Aber der ist zu ungenau.

Schon mal vielen Dank für Eure Hilfe.
Gruß, TheSaint
___________________________
[ XP Prof SP 3 | Vista | PB 4.30 ]
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

nuja... da das so eine sache ist, welche Funktion intern floats verwendet und welche für doubles geeignet ist,
ist mir das jetzt zu aufwendig dafür ne procedure zu schreiben die nachher doch nicht "genau genug" ist...

hast du das schon mal probiert, das über den umweg eines strings zu machen?
also erst StrD mit dementsprechend Nachkommastellen, und dann ValD?
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
TheSaint
Beiträge: 143
Registriert: 21.12.2008 18:59

Beitrag von TheSaint »

Hallo Kaeru Gaman,

vielen Dank für Deine Antwort.
Kaeru Gaman hat geschrieben:hast du das schon mal probiert, das über den umweg eines strings zu machen?
also erst StrD mit dementsprechend Nachkommastellen, und dann ValD?
Ja, habe ich versucht. Habe es aber wieder verworfen.
War zu ungenau. Deshalb dachte ich ja, das man die o. g.
Funktion in PB übersetzen könnte. Doch krieg ich das nicht hin.
Gruß, TheSaint
___________________________
[ XP Prof SP 3 | Vista | PB 4.30 ]
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

nunja....
kann man natürlich, allerdings arbeitet Pow() soweit ich weiß mit Float,
da wird man also niemals die genauigkeit von Double erreichen können.

davon ab... "War zu ungenau" ist halt eine recht abenteuerlich ungenaue aussage.

wo hat es denn geklemmt?

ehrlich gesagt halte ich eine lösung über ValD() und StrD() für das genaueste, was mit Standardtypen möglich ist.

ob du mit einer Übersetzung deiner Funktion überhaupt diese genauigkeit erreichst, ist noch die Frage.

außerdem... worauf stützt du denn deine Aussage "ist ungenau"?
... auf die Rückgabewerte irgendwelcher anderer Funktionen in VB oder SQL?
woher willst du denn wissen, dass diese Funktionen "genauer" sind?
du kannst doch nur sehen, dass sie ein anderes Ergebnis liefern....

und "absolute genauigkeit" ist mit Fließkommazahlen sowieso unmöglich,
und selbst mit spezial-libs oder sogar theoretisch nur in der Menge der Rationalen Zahlen möglich.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
TheSaint
Beiträge: 143
Registriert: 21.12.2008 18:59

Beitrag von TheSaint »

Hallo Kaeru Gaman,

vielen Dank für Deine Antwort.
Kaeru Gaman hat geschrieben:und "absolute genauigkeit" ist mit Fließkommazahlen sowieso unmöglich,
und selbst mit spezial-libs oder sogar theoretisch nur in der Menge der Rationalen Zahlen möglich.
Ich werde es noch mal versuchen. Vielen Dank.
Gruß, TheSaint
___________________________
[ XP Prof SP 3 | Vista | PB 4.30 ]
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag von mk-soft »

Mal Übersetzt

Code: Alles auswählen

Procedure.d SgnD(value.d)
  If value < 0.0
    ProcedureReturn -1.0
  ElseIf value > 0.0
    ProcedureReturn 1.0
  Else
    ProcedureReturn 0.0
  EndIf
EndProcedure

Procedure.d fctRound(varNr.d, varPl.i = 2)

  ;by Konrad Marfurt + ("" by) Luke Chung + Karl Donaubauer + to PB by mk-soft
  Protected result.d
  result = Round(varNr * Pow(10.0,varPl) + Sgnd(varNr) * 0.5, #PB_Round_Down) / Pow(10.0,varPl)
  ProcedureReturn result
  
EndProcedure

Debug fctRound(12.345678123456734567)
FF :wink:
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

wenn du schon Round einbaust, kannst du auch RoundNearest benutzen, und auf SgnD verzichten.

der Gäg sollte ja sein, auf Round zu verzichten.

also, wenn du eh zweimal Pow() drin hast und SgnD erstellt hast,
kannst du auch IntQ() zum beschneiten benutzen...

.... und wie gehabt, wenn Pow() nur mit Float arbeitet, ist das alles für die Füße.


... aber Monseur wollte ja nicht auf weiterführende Fragen antworten,
konnte nicht mal zum Ausdruck bringen, was er mit "ungenau" meint.
die Wahrscheinlichkeit ist hoch, dass es am IEEE 754 selber liegt.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag von mk-soft »

Jup,

Ich weis auch das es einfacher geht. Pow braucht man ja nur um auf die nachkommastellen zu kommen. Da reicht ein Float.

wenn man das ganze auch Float umsetzt schmeist der Debugger (Wohl Intern alles auf Double) einen ungenauen Wert raus.

Code: Alles auswählen

Procedure.d fctRound2(varNr.d, varPl.i = 2)

  ;by Konrad Marfurt + ("" by) Luke Chung + Karl Donaubauer + to PB by mk-soft
  Protected result.d
  result = Round(varNr * Pow(10.0,varPl), #PB_Round_Nearest) / Pow(10.0,varPl)
  ProcedureReturn result
  
EndProcedure
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

> Pow braucht man ja nur um auf die nachkommastellen zu kommen. Da reicht ein Float

hu?

Pow wird hier benutzt, um eine Zahl erst zu vergrößern und dann wieder zu verkleinern.
das macht die Ganze sache, die bei 32bit Float schon ungenau genug ist, noch ungenauer.
da wäre es schon wünschenswert, durchgehend mit Double arbeiten zu können.


die beste lösung wäre ein direktes FPU-Kommando.
wäre chique wenn es so eins gäbe...
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Beitrag von mk-soft »

Intern immer mit Double Rechnen. Sehe da kein Problem für die meisten Anwendungen. Pow(...) rechnet auch mit Double
Alles was daüber liegt reicht eine FPU auch nicht mehr und muss über APM Routinen berechnet werden.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Antworten