Kommata im Float?

  • Original von uschu.do
    wenn mein NSString preis = @"1.234,56"; dann kann ich

    Quellcode

    1. NSArray * preisComps = [preis componentsSeparatedByString:@".,"];
    2. NSString * preisString = [preisComps componentsJoinedByString:@""];
    3. int preisCent = [preisString intValue];


    Das funzt auch mit @"1,234.56".

    Warum komplizierter als nötig?

    Weil dann nicht @"1.234.567" = @"1.234,567" ist. Und das ist bestimmt nicht richtig.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Auch Dezimals können sich "verrunden". Sie tun das nur hübscher. Aber gegen NSDecimalNumbers habe ich auch nichts. Bloß Floats haben bei finanzmathematischen Anwendungen nichts (eigentlich: nicht im Ergebnis) zu suchen.
    +++
    Vllt sollte ich das allgemeiner klar machen:

    Alle Floats, auch Decimal-Numbers stellen einen Bruch dar. Die Menge der Brüche ist "kontinuierlich", also nicht diskret. (Nein, jetzt bitte nicht noch eine Diskussion darüber, ob irrationale Zahlen zwischen über oder in Brüchen liegen.)

    Alle im Computer dargestellten Zahlen sind diskret. Das ergibt sich spätestens aus der Menge des zur Verfügung stehenden Speichers.

    Daher kann es keine digitale Repräsentation von Brüchen geben. Egal wie ich das mache, es kann niemals funktionieren. Deshalb versprechen alle Floats einschließlich Decimal-Numbers etwas, was sie nicht halten können.

    Das verhindern nur ganzzahlige Typen. (Und die natürlich nur in einem gewissen Wertebereich.)
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Michael
    Original von Lucas de Vil
    a) int i = (int)([theString floatValue] * 100); // Alternativ * 100 für Zehntel Cent/ 3 Nachkommastellen

    Allein durch [theString floatValue] hast Du schon den ersten Rundungsfehler drin. Wenn es also sehr genau werden soll ist das eine schlechter Ansatz.

    Michael


    Ohne Locale wirds eh nix, weil er mit Komma drin ist.
    Aber viel gerundet dürfte da nicht werden.
    Aus 12345,678928 würde 1234567.
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Wenn das so im String steht, den Du übergeben bekommst

    3,45 EURO
    5,45 kg

    bleibt wohl nix anderes übrig, als das Ganze auseinanderzuklamüseln, wohl am besten mit Stringfunktionen (Klasse NSSString/NSMutableString). Das ist eingentlich relativ einfach. Schau in die Doku zu diesen Klassen.

    Du könntest damit beginnen, alles was nicht 0123456789,. ist, aus dem String rauszuschmeissen.

    Den String, der dann nur noch den Zahlenwert (in deutscher Komma-Version) enthält, wandelst Du dann ich eine Zahl um. Schau Dir dazu mal NSNumberFormatter an. Der wird für genau solche Zwecke in Eingabefeldern üblicherweise verwendet - scheint mir für Deine Zwecke also wie geschaffen.

    Ich würde übrigens auch in eine NSDecimalNumber umwandeln. Genau für Deine (kaufmännischen) Zwecke ist dieser u.a. da.

    No.
  • Original von BlackBerryUser
    Das Script, dass Du dort angeboten hast ist aber die andere Richtung.

    float zu String.

    Ich will doch vom String zum float.

    ja, ich habe da die Ausgabe reingeschrieben. In dem Thread geht's aber um beide Richtungen.

    Kurz: NSScanner mit NSLocale zum scannen, NSNumberFormatter zum Ausgeben. Als Typ NSDecimalNumber. Das sind zwar auch Brüche, aber sie bleiben bei Dezimalbrüchen bis zu 38 Stellen genau.
    Multigrad - 360°-Produktfotografie für den Mac
  • Halo Zusammen,

    kaufmännisches Runden: wird selten intern auf die 2.Stelle gerundet. Ich habe mir angewöhnt 1ct zu 1000 zu setzen, damit habe ich noch genügend "Stellen" um die MwSt. vernünftig zu addieren. Meine Empfehlung ist Geldwerte generell nur als Integer zu interpretieren. Da gibt es de wenigsten Probleme. Wer komplexe finanz. Berechnungen anstellen möchte (Aktienkurse, Zinsen, Devisen u.s.w.) sollte dann doch Dezimal verwenden (wenn der Kunde eine Bank ist;) ).

    Mann sollte auch niemals den Computer das Runden selber überlassen. printf (wird ja via der SDK oft genutzt) rundet nur scheinbar kaufmännisch, daher Vorsicht nicht verwenden.
    lt. C90: 7.9.6.1 - Der Wert wird auf die passende Anzahl der Stellen abgerundet.
    oder lt. C90: 6.2.1.3 - beim Umwandeln vom Fließkomma in einem Ganzzahl werden die Kommastelle abgeschnitten.

    Daher auch nicht die SDK das Runden übernehmen lassen. Ich hatte da schon öfter böse Überraschungen erlebt.
  • Das war ja ein lustiger Thread. Hatte ich damals wohl verpasst. Gleich mal nachholen!

    Ich versteh nicht so ganz, warum alle Angst vor Gleitkomma Zahlen haben. Ja, 4.8 ist intern 4.7999999999999998 (oder 4.80000019073486328125). Wenn man aber in Cent rechnet, sind es ausgegeben dennoch wieder 4.8 Cent. Und multiplizier den "ungenauen" Wert mit 1000 und du kommst auf 4800.00000000000, oh wunder.
    Wenn man durch längere Rechnungen befürchtet, das sich das irgendwie Aufsummiert, muss man halt schauen, dass seine Rechenverfahren numerisch stabil sind. Dafür bringt man Studenten an der Uni Numerik bei.
    Ob man nicht durch Fixpunkt-Zahlen andere Fehler einschleppt, will ich gar nicht wissen. Was passiert, wenn ich mal Deine 100 Euro als (int)10.000 Cent in drei gleichgroße Teile aufteilen muss, weil das meinetwegen meine Formel sagt? Da mach ich aber gleich schonmal einen viel größeren Fehler.
    C++
  • zerm schrieb:

    ...
    Ich versteh nicht so ganz, warum alle Angst vor Gleitkomma Zahlen haben. Ja, 4.8 ist intern 4.7999999999999998 (oder 4.80000019073486328125). Wenn man aber in Cent rechnet, sind es ausgegeben dennoch wieder 4.8 Cent. Und multiplizier den "ungenauen" Wert mit 1000 und du kommst auf 4800.00000000000, oh wunder.
    ....
    fast Richtig aber 4.8 ct oder 4.79 ct macht ein unterschied.
  • Kismet schrieb:

    zerm schrieb:

    ...
    Ich versteh nicht so ganz, warum alle Angst vor Gleitkomma Zahlen haben. Ja, 4.8 ist intern 4.7999999999999998 (oder 4.80000019073486328125). Wenn man aber in Cent rechnet, sind es ausgegeben dennoch wieder 4.8 Cent. Und multiplizier den "ungenauen" Wert mit 1000 und du kommst auf 4800.00000000000, oh wunder.
    ....
    fast Richtig aber 4.8 ct oder 4.79 ct macht ein unterschied.
    noch mal auf Deutsch wieso: bei eine Bierpfandflasche sind 0.0125ct MwSt enthalten. Nun gehen wir mal von einem Lager mit ca 90.000 Flaschen aus. Dann macht die 2. Kommastelle kaufmännisch sinn (so habe ich das gelernt). Wer zu früh rundet der Verschenkt Geld.
  • Kismet schrieb:

    zerm schrieb:

    ...
    Ich versteh nicht so ganz, warum alle Angst vor Gleitkomma Zahlen haben. Ja, 4.8 ist intern 4.7999999999999998 (oder 4.80000019073486328125). Wenn man aber in Cent rechnet, sind es ausgegeben dennoch wieder 4.8 Cent. Und multiplizier den "ungenauen" Wert mit 1000 und du kommst auf 4800.00000000000, oh wunder.
    ....
    fast Richtig aber 4.8 ct oder 4.79 ct macht ein unterschied.

    Natürlich. Du kommst aber nie an die 4.79ct. Ausser vielleicht durch super-fieses Pointer-casting.
    Was meinst Du wohl, was folgendes Programm ausgibt?

    C-Quellcode

    1. float value = 4.8f;
    2. float cent = 100.f;
    3. int iv = (int)(value*cent);
    4. printf("%d\n",iv);
    C++
  • zerm schrieb:

    Das war ja ein lustiger Thread. Hatte ich damals wohl verpasst. Gleich mal nachholen!

    Ich versteh nicht so ganz, warum alle Angst vor Gleitkomma Zahlen haben. Ja, 4.8 ist intern 4.7999999999999998 (oder 4.80000019073486328125). Wenn man aber in Cent rechnet, sind es ausgegeben dennoch wieder 4.8 Cent. Und multiplizier den "ungenauen" Wert mit 1000 und du kommst auf 4800.00000000000, oh wunder.
    Wenn man durch längere Rechnungen befürchtet, das sich das irgendwie Aufsummiert, muss man halt schauen, dass seine Rechenverfahren numerisch stabil sind. Dafür bringt man Studenten an der Uni Numerik bei.
    Ob man nicht durch Fixpunkt-Zahlen andere Fehler einschleppt, will ich gar nicht wissen. Was passiert, wenn ich mal Deine 100 Euro als (int)10.000 Cent in drei gleichgroße Teile aufteilen muss, weil das meinetwegen meine Formel sagt? Da mach ich aber gleich schonmal einen viel größeren Fehler.

    Mir schlottern auch nicht die Knie.

    Aber es ist

    a) manchmal schlicht nicht richtig

    b) summiert sich das auf.

    Ich hatte mal ein Problem, da ging es viel um Teilerverhältnisse. Spätestens nach drei Operationen hattest du nur noch Schwachsinn, was dann in eta 665/997 entsprach, aber nicht mehr 2/3.

    In der Musik würde man das wohl wohltemperiert nennen. Es war aber nicht meine Intention.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • zerm schrieb:

    Kismet schrieb:

    zerm schrieb:

    ...
    Ich versteh nicht so ganz, warum alle Angst vor Gleitkomma Zahlen haben. Ja, 4.8 ist intern 4.7999999999999998 (oder 4.80000019073486328125). Wenn man aber in Cent rechnet, sind es ausgegeben dennoch wieder 4.8 Cent. Und multiplizier den "ungenauen" Wert mit 1000 und du kommst auf 4800.00000000000, oh wunder.
    ....
    fast Richtig aber 4.8 ct oder 4.79 ct macht ein unterschied.

    Natürlich. Du kommst aber nie an die 4.79ct. Ausser vielleicht durch super-fieses Pointer-casting.
    Was meinst Du wohl, was folgendes Programm ausgibt?

    C-Quellcode

    1. float value = 4.8f;
    2. float cent = 100.f;
    3. int iv = (int)(value*cent);
    4. printf("%d\n",iv);


    Was sind denn 2,34 % von 1,00 €?
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Amin Negm-Awad schrieb:

    zerm schrieb:

    Das war ja ein lustiger Thread. Hatte ich damals wohl verpasst. Gleich mal nachholen!

    Ich versteh nicht so ganz, warum alle Angst vor Gleitkomma Zahlen haben. Ja, 4.8 ist intern 4.7999999999999998 (oder 4.80000019073486328125). Wenn man aber in Cent rechnet, sind es ausgegeben dennoch wieder 4.8 Cent. Und multiplizier den "ungenauen" Wert mit 1000 und du kommst auf 4800.00000000000, oh wunder.
    Wenn man durch längere Rechnungen befürchtet, das sich das irgendwie Aufsummiert, muss man halt schauen, dass seine Rechenverfahren numerisch stabil sind. Dafür bringt man Studenten an der Uni Numerik bei.
    Ob man nicht durch Fixpunkt-Zahlen andere Fehler einschleppt, will ich gar nicht wissen. Was passiert, wenn ich mal Deine 100 Euro als (int)10.000 Cent in drei gleichgroße Teile aufteilen muss, weil das meinetwegen meine Formel sagt? Da mach ich aber gleich schonmal einen viel größeren Fehler.

    Mir schlottern auch nicht die Knie.

    Aber es ist

    a) manchmal schlicht nicht richtig

    b) summiert sich das auf.

    Ich hatte mal ein Problem, da ging es viel um Teilerverhältnisse. Spätestens nach drei Operationen hattest du nur noch Schwachsinn, was dann in eta 665/997 entsprach, aber nicht mehr 2/3.

    In der Musik würde man das wohl wohltemperiert nennen. Es war aber nicht meine Intention.

    Was für Operationen? Das würde mich jetzt sehr interessieren. Hast Du noch den Quelltext und kannst mir den Ausschnitt zukommen lassen? Drei Operationen ist echt hart. Aber sowas kann bspw. passieren, wenn Du Zahlen von extrem unterschiedlicher Größenordnung miteinander kombinierst. Zeig mal, damit ich sehen kann, was es bei Dir war. Das wäre lieb :)
    C++
  • Mal ein kleines Beispiel: Cents aufsummieren.

    Quellcode

    1. float a = 0.0f;
    2. for (int i=0;i<100000;i++) a += 0.01f;
    3. NSLog(@"1000 = %f",a);
    4. float b = 0.0f;
    5. for (int i=0;i<1000000;i++) b += 0.01f;
    6. NSLog(@"10000 = %f",b);

    Einmal Hunderttausend Cent, einmal eine Million. Beide Ergebnisse sind für kaufmännische Berechnungen unbrauchbar: Einmal kommt 1000.665039 raus, einmal 9865.223633. Einmal zu viel, einmal zu wenig. Nicht wirklich gut vorhersagbar. Der zweite Fall lässt sich durch Rundungsfehler der Mantisse bei der Exponentenangleichung für die Addition erklären. Der erste Fall dadurch, dass sich 0,01 nicht exakt als float darstellen lässt. Hey, Ihr wollt doch wohl nicht ernsthaft für Geldberechnungen ein Werkzeug benutzen, das nicht in der Lage ist, einen Cent genau darzustellen, oder? Mit doubles lassen sich die Effekte verzögern, aber sie sind genau so da.

    Wer mit floats richtig rechnen will, muss mit Intervallarithmetik hantieren. Das ist erheblich weniger Spaß als NSDecimalNumber...
    Multigrad - 360°-Produktfotografie für den Mac
  • zerm schrieb:

    Was passiert, wenn ich mal Deine 100 Euro als (int)10.000 Cent in drei gleichgroße Teile aufteilen muss, weil das meinetwegen meine Formel sagt? Da mach ich aber gleich schonmal einen viel größeren Fehler.

    Da es materiell keine kleinere Einheit als den Cent gibt wirst du einfach nur kläglich scheitern.
    Egal ob mit int, GCfloat oder NSDecimal;)
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • zerm schrieb:

    Amin Negm-Awad schrieb:

    Was sind denn 2,34 % von 1,00 €?

    Ja, was sinds denn?
    Mit dem obigen Programm komme ich auf genau 2340/1000 cent (wenn ich "cent" auf 100.000 setze). Mit FP.
    Hier wärs jetzt doof gelaufen, wenn ich mit "cent" als 10.000 gerechnet hätte, da wär schön was weggefallen. Aber kommt halt eben genau auf das Problem an. Ich würde Dir auch nur 2ct geben :)

    Was du mir geben würdest, ist gerade irrelevant.

    Die Bank gibt dir 0,02 €. Und wenn das an 10 Tagen hintereinander geschieht, sind es noch 0,20 € und nicht 0,23 €.

    Das Problem ist übrigens benannt.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • zerm schrieb:

    Amin Negm-Awad schrieb:

    zerm schrieb:

    Das war ja ein lustiger Thread. Hatte ich damals wohl verpasst. Gleich mal nachholen!

    Ich versteh nicht so ganz, warum alle Angst vor Gleitkomma Zahlen haben. Ja, 4.8 ist intern 4.7999999999999998 (oder 4.80000019073486328125). Wenn man aber in Cent rechnet, sind es ausgegeben dennoch wieder 4.8 Cent. Und multiplizier den "ungenauen" Wert mit 1000 und du kommst auf 4800.00000000000, oh wunder.
    Wenn man durch längere Rechnungen befürchtet, das sich das irgendwie Aufsummiert, muss man halt schauen, dass seine Rechenverfahren numerisch stabil sind. Dafür bringt man Studenten an der Uni Numerik bei.
    Ob man nicht durch Fixpunkt-Zahlen andere Fehler einschleppt, will ich gar nicht wissen. Was passiert, wenn ich mal Deine 100 Euro als (int)10.000 Cent in drei gleichgroße Teile aufteilen muss, weil das meinetwegen meine Formel sagt? Da mach ich aber gleich schonmal einen viel größeren Fehler.

    Mir schlottern auch nicht die Knie.

    Aber es ist

    a) manchmal schlicht nicht richtig

    b) summiert sich das auf.

    Ich hatte mal ein Problem, da ging es viel um Teilerverhältnisse. Spätestens nach drei Operationen hattest du nur noch Schwachsinn, was dann in eta 665/997 entsprach, aber nicht mehr 2/3.

    In der Musik würde man das wohl wohltemperiert nennen. Es war aber nicht meine Intention.

    Was für Operationen? Das würde mich jetzt sehr interessieren. Hast Du noch den Quelltext und kannst mir den Ausschnitt zukommen lassen? Drei Operationen ist echt hart. Aber sowas kann bspw. passieren, wenn Du Zahlen von extrem unterschiedlicher Größenordnung miteinander kombinierst. Zeig mal, damit ich sehen kann, was es bei Dir war. Das wäre lieb :)

    Nein,

    a) weil mein damaliger Arbeitgeber die Nutzungsrechte hat und

    b) es Ewigkeiten her ist.

    Aber ich kann es dir erläutern, was geschah:

    Es ging darum, dass ein System mit einem (einstellbaren) Takt vorhanden war. Innerhalb des Taktes sollten von verschiedenen Modulen in unterschiedlichen Frequenzen Werte gelesen werden, wobei innerhalb eines Taktes beliebig viele Module gelesen werden konnten. (Die Grenze ergab sich nur aus dem gesamtdatendurchsatz, weil die Module ihre Werte synchron in DPRAMs pufferten.)

    Also:
    Modul 1: 1000 MHz
    Modul 2: 500 Mhz
    Modul 3: 1000 MHz
    Modul 4: 250 MHz
    Modul 5: 200 MHz

    Aufgabe: Was ist der kleinste Takt, zu denen alle Module exakt gelesen werden können? (Vertiefung: Wenn dieser über dem höchstmöglichen Takt liegt, was ist der beste noch mögliche Takt?) Wir lang ist ein kompletter Zyklus? In Welchen Phase müssen welche Module gelesen werden (Abtastprogramm)?

    Du wirst schnell sehen, dass das mit Verhältnissen zusammenhängt. Wenn du jetzt einmal 0,249999 statt 0,25 stehen hast, wirst du einsehen, dass das Abtastprogramm von dramtischer Länge wird, der Takt sehr hoch und die meisten Zyklen unbesetzt sind. Das Gegenteil von dem, was es soll.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Amin Negm-Awad ()

  • mattik schrieb:

    Einmal Hunderttausend Cent, einmal eine Million. Beide Ergebnisse sind für kaufmännische Berechnungen unbrauchbar: Einmal kommt 1000.665039 raus, einmal 9865.223633. Einmal zu viel, einmal zu wenig.

    Ja, Addition ist numerisch instabil. Ich will ja auch nicht die Probleme leugnen, mir ist nur eben nicht bekannt, wo das in der Praxis (=Finanzen) anfängt, eine Rolle zu spielen. Dein Beispiel kann ich mir eben praktisch nicht so recht vorstellen, dass ich eine Million mal ein Cent irgendwo hinzu addieren muss. Hier kann man aber die Rechnung umstellen auf die numerisch stabile Multiplikation.
    Naja, so ein wenig kann ich mir vorstellen, dass es Probleme geben könnte, wenn ich die Beträge von 1000 Kassen in ganz Deutschland einfach blind drauf los mit Floatingpoints aufsummiere. Hmm.

    Amin Negm-Awad schrieb:

    Die Bank gibt dir 0,02 €. Und wenn das an 10 Tagen hintereinander geschieht, sind es noch 0,20 € und nicht 0,23 €.

    Das wäre doch aber ziemlich doof oder stehe ich grade auf dem Schlauch? Wird mir 1ct über ein Tag anders verzinst als 100ct?
    Ok, _hintereinander_, wohl. Aber das macht die Bank ja nicht. Aber mir dämmert, was Du mir sagen willst. Die Bank zahlt mir nicht Hunderstelcent, ja.

    Amin Negm-Awad schrieb:

    Aber ich kann es dir erläutern, was geschah:

    Vielen Dank, ich denke da mal drüber nach.
    C++