select mit Dezimalzahlen

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Micky91
Beiträge: 35
Registriert: 06.11.2013 19:35

select mit Dezimalzahlen

Beitrag von Micky91 »

Folgende Situation. Ich habe Dezimalzahlen (1, 1.5, 2, 2.5, 3, 3.5 ...)
Mit den .5 Zahlen geht dies nicht und bringt immer das Ergebnis für den ersten Wert (1)
In der Dokumentation steht, das beim Befehl "select" die Zahlen aufgerundet werden.
Also dachte ich mir, ich wandle die Zahlen in einen String um (strg($x))
Doch leider werden zwar jetzt alle Ganzzahlen richtig interpretiert, aber die.5 Werte weiterhin nicht.
Was mach ich da falsch?

Code: Alles auswählen

select Str(*Cache\difficulty)
    Case "1"
      diffimage$ = GetCurrentDirectory() + image_star_1_0$
    Case "1.5"
      diffimage$ = GetCurrentDirectory() + image_star_1_5$
    Case "2"
      diffimage$ = GetCurrentDirectory() + image_star_2_0$
    Case "2.5"
      diffimage$ = GetCurrentDirectory() + image_star_2_5$
    Case "3"
      diffimage$ = GetCurrentDirectory() + image_star_3_0$
    Case "3.5"
      diffimage$ = GetCurrentDirectory() + image_star_3_5$
    Case "4"
      diffimage$ = GetCurrentDirectory() + image_star_4_0$
    Case "4.5"
      diffimage$ = GetCurrentDirectory() + image_star_4_5$
    Case "5"
      diffimage$ = GetCurrentDirectory() + image_star_5_0$
 EndSelect
PureBasic 5.72 (x64) | Mac OSX 10.15.6
Benutzeravatar
mk-soft
Beiträge: 3700
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: select mit Dezimalzahlen

Beitrag von mk-soft »

Code: Alles auswählen

fVal.f = 1.5
iVal.i = (fVal * 10.0)
Debug iVal

Select iVal
    Case 10
      diffimage$ = GetCurrentDirectory() + image_star_1_0$
    Case 15
      diffimage$ = GetCurrentDirectory() + image_star_1_5$
    Case 20
      diffimage$ = GetCurrentDirectory() + image_star_2_0$
    Case 25
      diffimage$ = GetCurrentDirectory() + image_star_2_5$
    Case 30
      diffimage$ = GetCurrentDirectory() + image_star_3_0$
    Case 35
      diffimage$ = GetCurrentDirectory() + image_star_3_5$
    Case 40
      diffimage$ = GetCurrentDirectory() + image_star_4_0$
    Case 45
      diffimage$ = GetCurrentDirectory() + image_star_4_5$
    Case 50
      diffimage$ = GetCurrentDirectory() + image_star_5_0$
 EndSelect
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: select mit Dezimalzahlen

Beitrag von GPI »

Ich denke du bist über das Problem gestolpert, das Floats immer "schätzwerte" sind.

kannst du einfach mit einen

Code: Alles auswählen

debug Str(*Cache\difficulty)
überprüfen

wobei STR falsch ist - das ist für integer, du suchst StrF bzw. StrD

Wobei ich das vermutlich anders lösen würde. bspw. mit zwei Variablen. bspw. so:

Code: Alles auswählen

Difficult.i=3
DiffFactor.d=Difficult/2.0 
das .0 ist wichtig, damit PB gezwungen wird, in Double zu berechnen..
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: select mit Dezimalzahlen

Beitrag von Nino »

Micky91 hat geschrieben:Folgende Situation. Ich habe Dezimalzahlen (1, 1.5, 2, 2.5, 3, 3.5 ...)
Mit den .5 Zahlen geht dies nicht und bringt immer das Ergebnis für den ersten Wert (1)
In der Dokumentation steht, das beim Befehl "select" die Zahlen aufgerundet werden.
Also dachte ich mir, ich wandle die Zahlen in einen String um (strg($x))
Doch leider werden zwar jetzt alle Ganzzahlen richtig interpretiert, aber die.5 Werte weiterhin nicht.
Was mach ich da falsch?
Folgendes steht dazu in der Dokumentation von Select:
Hinweis: Select akzeptiert auch Fließkommazahlen (Floats) als <Ausdruck1>, rundet diese jedoch auf die nächstgelegene Ganzzahl (Integer) ab (Vergleiche werden nur mit Ganzzahlen durchgeführt).
Ich finde die Aussage klar.

In der Konsequenz bedeutet das, dass Du entweder Ganzzahlen benutzen solltest (wie von mk-soft vorgeschlagen) oder statt Select/Case lauter If/ElseIf-Zweige (wobei dann allerdings das Problem mit der allgemeinen Fließkommazahlen-Ungenauigkeit auftreten kann, das GPI schon ansprach).
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8679
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: select mit Dezimalzahlen

Beitrag von NicTheQuick »

0.5er-Werte sind aber in der Regeln genau. Denn 0,5 = 2^(-1), ist also korrekt darstellbar in Binärform. Das sollte also mit If-Else funktionieren.

Idealerweise arbeitet man bei Vergleichen mit Fließkommazahlen allerdings mit einem Epislon und Differenzen:

Code: Alles auswählen

If Abs(soll - ist) < Epsilon : Tuwas : EndIf
Wobei Epsilon ein möglichst kleiner Wert ist, z.B. 0.00001. Je nachdem wie hoch die Genauigkeit sein soll.

__________________________________________________
Code-Tags repariert
25.04.2017
RSBasic
Bild
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Re: select mit Dezimalzahlen

Beitrag von GPI »

Falls sich wer fragt, was ich mit ungenauigkeit meine:

Code: Alles auswählen

a.f=0.4
b.f

For i=1 To 100000
  b+a
Next
Debug "b:"+b
Debug "a:"+a


c.d=0.4
d.d

For i=1 To 100000
  d+c
Next
Debug "d:"+d
Debug "c:"+c
Debug "c:"+StrD(c,17)
0.4 lässt sich nicht binär darstellen. Das ist aber kein Fehler, wir haben in 10er-System das gleiche mit 1/3. Jenachdem wie diese 0.5 berechnet werden, kann es zu ungenauigkeiten kommen. Deshalb bspw. das Konstrukt von Nic mit Epsilon.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Antworten