Umwandlung eines Strings in eine Zahl

Anfängerfragen zum Programmieren mit PureBasic.
Mike32
Beiträge: 41
Registriert: 27.05.2012 14:24

Umwandlung eines Strings in eine Zahl

Beitrag von Mike32 »

Nachdem ich nun ein Inputrequester habe, welches eine Dezimalzahl erfasst, möchte ich den String zu einer Zahl umwandeln.
Der folgende Beispielcode ergibt jedoch eine falsch Zahl.

Wert$="1.2"
Wert1.f=ValF(Wert$)

Wert1 ergibt aber eigenartigerweise: 1.2000000476837158 :o
Gibt es hierfür eine Lösung?

Ich hatte mir dann gedacht, er sollte nach der 2.Kommastelle die Zahl einfach abschneiden (nicht runden!), so dass dann 1.20 rauskäme. - Leider habe ich jedoch hierfür keine Lösung gefunden.

Aber auch der Round-Befehl funktioniert nicht sauber, da man ihm nicht vorgeben kann, dass er erst ab der 2. Nachkommastelle runden soll.
Ich will einfach als Endergebnis der ursprünglichen Eingabe einen Geldbetrag mit 2 Nachkommastellen.

Kann mir jemand helfen?

Grüße

Mike
c4s
Beiträge: 1235
Registriert: 19.09.2007 22:18

Re: Umwandlung eines Strings in eine Zahl

Beitrag von c4s »

Das seltsame Verhalten der Nachkommastellen gehört nun mal zu den Fließkommazahlen (in PureBasic Float bzw. Double). Mehr Informationen dazu sollten sich im Web, der PB-Hilfe oder dem Forum finden lassen.

Code: Alles auswählen

Debug ValF("1.2", 2)
"Menschenskinder, das Niveau dieses Forums singt schon wieder!" — GronkhLP ||| "ich hogffe ihr könnt den fehle endecken" — Marvin133 ||| "Ideoten gibts ..." — computerfreak ||| "Jup, danke. Gruss" — funkheld
Mike32
Beiträge: 41
Registriert: 27.05.2012 14:24

Re: Umwandlung eines Strings in eine Zahl

Beitrag von Mike32 »

Vielen Dank!

Ich werde wohl die Eingabe per Programmierung analysieren und umwandeln müssen.
Schade


Grüße

Mike
Benutzeravatar
Falko
Admin
Beiträge: 3535
Registriert: 29.08.2004 11:27
Computerausstattung: PC: MSI-Z590-GC; 32GB-DDR4, ICore9; 2TB M2 + 2x3TB-SATA2 HDD; Intel ICore9 @ 3600MHZ (Win11 Pro. 64-Bit),
Acer Aspire E15 (Win11 Home X64). Purebasic LTS 6.11b1
HP255G8 Notebook @AMD Ryzen 5 5500U with Radeon Graphics 2.10 GHz 3.4GHz, 32GB_RAM, 3TB_SSD (Win11 Pro 64-Bit)
Kontaktdaten:

Re: Umwandlung eines Strings in eine Zahl

Beitrag von Falko »

Und wie wäre es mit ValD und Wert1.D?
PB-Hilfe hat geschrieben:Hinweis: Strings mit einer enthaltenen Ganzzahl können auch mit Val() und 32 Bit-Fließkommazahlen mit ValF() (mit geringerer Genauigkeit als ValD()) konvertiert werden
Gruß,
Falko
Bild
Win11 Pro 64-Bit, PB_6.11b1
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Re: Umwandlung eines Strings in eine Zahl

Beitrag von DarkDragon »

1.2 ist durch keine endliche Folge von Zweierpotenzen beschreibbar, da hilft weder double noch float:

Code: Alles auswählen

Vorkommaanteil:
    1 (Dezimal)
  = 2^0
  = 1 (Binär)

+

Nachkommaanteil:
   0.2 (Dezimal)
 = Summe für i von 1 bis UNENDLICH aus (2^(-4*i+1) + 2^(-4*i))
 = 2^(-3) + 2^(-4) + 2^(-7) + 2^(-8) + ...
 = 001100110011 ... (Binär)

0.2  * 2 = 0.4 + 0
0.4  * 2 = 0.8 + 0
0.8  * 2 = 0.6 + 1
0.6  * 2 = 0.2 + 1
0.2  * 2 = 0.4 + 0 (Periode)
Für deine Anwendungen wären wohl Festkommazahlen vermutlich besser geeignet.
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8808
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Umwandlung eines Strings in eine Zahl

Beitrag von NicTheQuick »

Wenn es um Geld geht, sollten IMMER Ganzzahlen verwendet werden und NIE Fließkommazahlen. Dazu rechnet man einfach mit Cent und fügt das Komma ein, wenn es angezeigt werden muss.
sibru
Beiträge: 265
Registriert: 15.09.2004 18:11
Wohnort: hamburg

Re: Umwandlung eines Strings in eine Zahl

Beitrag von sibru »

So geht´s auch:

Code: Alles auswählen

;Modul      Str2NumD Version 1.02 vom 27.09.2009 
#PB_Vers  = "4.20"            
;
;Funktion:  ValD() ohne Ungenauigkeit
;           Mit dieser Funktion kann ein nummerischer String fehlerfrei zu einem
;           Double-Wert umgesetzt werden (Str2NumD("0.11") liefert 0.11, die Orginal=
;           Funktion ValD("0.11") liefert 0.10999999 ...)
;           Nur bei hoher Genauigkeits-Anforderung oder gelegentlichem Aufruf anzuwenden,
;           da wg. String-Fnc´s sehr langsam...
;
;
;Aufruf:    ZahlenWert.d = Str2NumD(NumStr$)
;           NumStr$: kann Text mit nummerischen Wert enthalten. Vor- und NachKommaStellen-
;                    Trennzeichen kann Punkt (.) oder auch Kommata (,) sein oder auch ganz
;                    entfallen. Führende oder abschließende 0en nicht erforderlich
;                    (",123" --> 0.123   "123," --> 123)
;           Es wird der entsprechende nummerische Double-Wert zurückgeliefert
;

;#jaPBeExt exit
Procedure.d Str2NumD(NumStr$)
  Protected Komma = FindString(NumStr$, ".", 1)
  If Komma = 0 : Komma = FindString(NumStr$, ",", 1): EndIf
  If Komma
    NumStr$ = Left(NumStr$, Komma - 1) + Mid(NumStr$, Komma + 1)
    ProcedureReturn Val(NumStr$) / Pow(10, Len(NumStr$) - Komma + 1)
  Else
    ProcedureReturn ValD(NumStr$)
  EndIf
EndProcedure
Bild Bild
Mike32
Beiträge: 41
Registriert: 27.05.2012 14:24

Re: Umwandlung eines Strings in eine Zahl

Beitrag von Mike32 »

Hmm,

zuerst vielen Dank für die vielen Tipps.
Ich denke, dass ich ziemlich aufwändig bei der Eingabe abklären muss, ob man z.B. Komma oder Buchstaben eingegeben hat und entsprechend rausfiltern bzw. umwandeln.

Grüße

Mike
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8808
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Umwandlung eines Strings in eine Zahl

Beitrag von NicTheQuick »

@sibru:

Erstens. Ich sehe da keinen Unterschied:

Code: Alles auswählen

Procedure.d Str2NumD(NumStr$)
	Protected Komma = FindString(NumStr$, ".", 1)
	If Komma = 0 : Komma = FindString(NumStr$, ",", 1): EndIf
	If Komma
		NumStr$ = Left(NumStr$, Komma - 1) + Mid(NumStr$, Komma + 1)
		ProcedureReturn Val(NumStr$) / Pow(10, Len(NumStr$) - Komma + 1)
	Else
		ProcedureReturn ValD(NumStr$)
	EndIf
EndProcedure

Debug Str2NumD("0.11")
Debug ValD("0.11")
Debugger hat geschrieben:0.1100000000000000005551115
0.1100000000000000005551115
Es kommt da auch nirgendwo 0.10999999 raus.

Zweitens. Man kann Fließkommazahlen nicht genauer machen. Sie arbeiten mit dem Binärsystem.
Genau wie du im Dezimalsystem ⅓ als 0.33333333333… darstellen musst, wäre es im Dreiersystem lediglich 0.1, also ohne Periode.
0.1 im Dezimalsystem wäre im Binärsystem dann 0.00011001100110011..., also wiederum periodisch und somit unendlich lang. Die Zahl 0.1 kann man also im Binärsystem nicht exakt speichern, weshalb die Nachkommastellen ab einer bestimmten Stelle abgeschnitten werden. Bei der Rücktransformation ins Dezimalsystem tauchen diese fehlenden Nachkommastellen dann wieder als Fehler auf. Nehmen wir mal an, wir hätten die Binärdarstellung so beschnitten: 0.00011001100110011, dann käme nach der Umwandlung ins Dezimalsystem das hier raus: 0.09999847412109375.
BSP
Beiträge: 201
Registriert: 01.02.2009 14:04

Re: Umwandlung eines Strings in eine Zahl

Beitrag von BSP »

Hallo.
Ich muss gestehen, in diesem Fall verstehe ich das Problem nicht.
Ich arbeite mit folgendem Prinzip und hatte bisher noch keine Probleme.
Oder waren bisher meine Geldbeträge zu gering? Smile.

Code: Alles auswählen

Enumeration
  #TasteReturn
EndEnumeration

Define zahl.d
Define zahl$

OpenWindow(1,0,0,200,100,"Rechnen",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
AddKeyboardShortcut(1,#PB_Shortcut_Return,#TasteReturn)
StringGadget(1,4,4,192,24,"")
TextGadget(2,4,32,192,24," €")
SetActiveGadget(1)
Repeat
ev=WaitWindowEvent()

If ev=#PB_Event_CloseWindow
  ende=1
EndIf

If ev=#PB_Event_Menu And EventMenu()=#TasteReturn
  zahl$=GetGadgetText(1)
  ReplaceString(zahl$, "," , "." , #PB_String_InPlace)
  zahl=ValD(zahl$)
  
  zahl$=GetGadgetText(2)
  ReplaceString(zahl$, "," , "." , #PB_String_InPlace)
  zahl+ValD(zahl$)
  
  zahl$=StrD(zahl,2)
  ReplaceString(zahl$, "." , "," , #PB_String_InPlace)
  SetGadgetText(2,zahl$ +" €")
  SetGadgetText(1,"")
EndIf
Until ende
Gruß: Bernd
PB 5.31 (x86) & (x64) Win10
Antworten