Seite 1 von 2
Umwandlung eines Strings in eine Zahl
Verfasst: 07.06.2012 00:16
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
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
Re: Umwandlung eines Strings in eine Zahl
Verfasst: 07.06.2012 00:22
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.
Re: Umwandlung eines Strings in eine Zahl
Verfasst: 07.06.2012 09:32
von Mike32
Vielen Dank!
Ich werde wohl die Eingabe per Programmierung analysieren und umwandeln müssen.
Schade
Grüße
Mike
Re: Umwandlung eines Strings in eine Zahl
Verfasst: 07.06.2012 10:37
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
Re: Umwandlung eines Strings in eine Zahl
Verfasst: 07.06.2012 11:06
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.
Re: Umwandlung eines Strings in eine Zahl
Verfasst: 07.06.2012 13:15
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.
Re: Umwandlung eines Strings in eine Zahl
Verfasst: 07.06.2012 16:39
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
Re: Umwandlung eines Strings in eine Zahl
Verfasst: 07.06.2012 22:13
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
Re: Umwandlung eines Strings in eine Zahl
Verfasst: 08.06.2012 01:53
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.
Re: Umwandlung eines Strings in eine Zahl
Verfasst: 08.06.2012 03:08
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