DefaultFormatSettings.DecimalSeparator

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

DefaultFormatSettings.DecimalSeparator

Beitrag von corpsman »

Servus,

Ich schreibe jede Menge Plattform unabhängige SW (Linux und Windows) welche viel auf Deutschen und Englischen Rechnern läuft.

Natürlich verarbeiten meine Programme auch jede Menge Floatingpoint Zahlen.

Damit ich mit den Ländereinstellungen der diversen Rechner nicht komplett gegen die Wand laufe steht im OnCreate Code meiner Unit1 immer folgendes :

DefaultFormatSettings.DecimalSeparator := '.'

Nun kommt es aber immer wieder vor, dass nach "Langer" Laufdauer meiner Anwendung aus heiterem Himmel eine AV mit dem Text :

Projekt project1 hat Exception-Klasse >>EConvertError<< ausgelöst mit der Meldung:
"1.2" is an invalid float


Wird der DefaultFormatSettings.DecimalSeparator von irgendwelchen LCL Komponenten etwa wieder anders gesetzt ?
Habt ihr das Auch ?
--
Just try it

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: DefaultFormatSettings.DecimalSeparator

Beitrag von wp_xyz »

Ich habe mal das Lazarus und FPC-Verzeichnis nach dem Wort "FormatSettings" durchsucht und bin neben SysUtils und WinLazUtf8 (wo diese erstmals definiert werden) tatsächlich auf drei Stellen gestoßen, bei denen schreibend auf die FormatSettings zugegriffen wird: zweimal in LazReport (LR_Class.FormatValue und LR_Utils.lrNormalizeLocaleFloats) und einmal in laz2_xmlcfg.ExtendedToStr. Beim ersten und letzten Fall handelt es sich um temporäre Umstellungen, die innerhalb derselben Prozedur wieder aufgehoben werden, allerdings ohne den in solchen Fällen obligatorischen try-finally Block - wenn es also irgendwo in dieser Routine zu einer Exception kommt, wird evtl der alte Dezimaltrenner nicht wiedergeherstellt. Noch kritischer sehe ich die Umstellung in LZ_Utils.lrNormalizeLocaleFloats, einer Prozedur, die einmal mit Parameter true und dann wieder mit false aufgerufen werden muss - keine Ahnung, was dazwischen passiert!

Du solltest dazu einen Bugreport aufmachen. Heute erlaubt jede Konvertierungfunktion, eine lokale Kopie der Formatsettings als Parameter anzugeben.

Generell finde ich aber auch dein Vorgehen, dem Benutzer bestimmte Formatsettings aufzuwingen, unschön. Bei uns in Deutschland heißt es nun mal "null komma fünf", nicht "null punkt fünf". Bei mir verschwindet solche Software sofort wieder von der Platte.

BeniBela
Beiträge: 308
Registriert: Sa 21. Mär 2009, 17:31
OS, Lazarus, FPC: Linux (Lazarus SVN, FPC 2.4)
CPU-Target: 64 Bit

Re: DefaultFormatSettings.DecimalSeparator

Beitrag von BeniBela »

wp_xyz hat geschrieben:Generell finde ich aber auch dein Vorgehen, dem Benutzer bestimmte Formatsettings aufzuwingen, unschön. Bei uns in Deutschland heißt es nun mal "null komma fünf", nicht "null punkt fünf". Bei mir verschwindet solche Software sofort wieder von der Platte.


Ich schreib immer 0.5 und 2016-06-29, und die Software soll das dann auch annehmen

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6200
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: DefaultFormatSettings.DecimalSeparator

Beitrag von af0815 »

Ich erwarte, das das, was in den Systemeinstellungen angeben wird, auch verwendet wird. Somit sollte auch das richtig verwendet werden, was am 10er Block als Dezimaltrenner angeben ist.

Wenn wer den Punkt haben will, so kann er gerne seine Systemeinstelllungen anpassen, dazu sind sie ja da, aber nicht von der Software overruled werden.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: DefaultFormatSettings.DecimalSeparator

Beitrag von wp_xyz »

wp_xyz hat geschrieben:Du solltest dazu einen Bugreport aufmachen. Heute erlaubt jede Konvertierungfunktion, eine lokale Kopie der Formatsettings als Parameter anzugeben.

Die Stelle in Laz2_XmlCfg habe ich inzwischen selbst geändert.

BeniBela
Beiträge: 308
Registriert: Sa 21. Mär 2009, 17:31
OS, Lazarus, FPC: Linux (Lazarus SVN, FPC 2.4)
CPU-Target: 64 Bit

Re: DefaultFormatSettings.DecimalSeparator

Beitrag von BeniBela »

af0815 hat geschrieben:Wenn wer den Punkt haben will, so kann er gerne seine Systemeinstelllungen anpassen, dazu sind sie ja da, aber nicht von der Software overruled werden.


Es gibt auch Software, da kann man beides eingeben, z.b:: am Geldautomaten

wp_xyz hat geschrieben:
wp_xyz hat geschrieben:Du solltest dazu einen Bugreport aufmachen. Heute erlaubt jede Konvertierungfunktion, eine lokale Kopie der Formatsettings als Parameter anzugeben.

Die Stelle in Laz2_XmlCfg habe ich inzwischen selbst geändert.


deshalb verwende ich meinen HTML-Parser als XML-Parser

Die LCL ist voller unerwartetem Murks

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: DefaultFormatSettings.DecimalSeparator

Beitrag von wp_xyz »

BeniBela hat geschrieben:Die LCL ist voller unerwartetem Murks

Gut zu wissen, dass es wenigstens einen gibt, der keinen Murks macht.

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: DefaultFormatSettings.DecimalSeparator

Beitrag von corpsman »

Hmm,

Hmm dem User das so an zu zeigen wie er es im System gespeichert hat ist eine Sache. Aber wie gehe ich damit um, dass ich sowas auf einem Deutschen System speichere und dann auf einem Englischem lade ?

Code: Alles auswählen

 
var ini:TInifile;
begin
..
ini.writestring('as','asd',format('%1.fx%1.f',[1.5,1.6]));
 
 


Auf de gespeichert stünde nun "1,5x1,6"
das gibt ärger, wenn ich das auf meinem Englischen System wieder zerlege und nach float umwandle ..
--
Just try it

Mathias
Beiträge: 6165
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: DefaultFormatSettings.DecimalSeparator

Beitrag von Mathias »

Bei uns in Deutschland heißt es nun mal "null komma fünf", nicht "null punkt fünf". Bei mir verschwindet solche Software sofort wieder von der Platte.

Bei uns in der Schweiz, sagen wir auch null komma fünf, auf dem PC schreiben wir aber 0.5, auf dem Papier 0,5.
Nach meiner Meinung gehört auf dem PC der Punkt und nicht das Komma, aber da gibt es wohl Meinungsverschiedenheiten.
Das Komma wurde erst mit dem Office-Gerümpel eingeführt.

@corpsman

Wen du zwingen den Punkt habe willst, dann nimmst am besten für String/Float - Umwandlungen Str und Val, da wird immer mit einem Punkt gearbeitet, egal was in den Ländereinstellungen steht. :wink:
Das lustige dabei, StrToFloat und FloatToStr nehmen intern über einen riesen Overhead auch Str und Val. :mrgreen:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6165
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: DefaultFormatSettings.DecimalSeparator

Beitrag von Mathias »

ini.writestring

Ich sehe gerade, du brauchst das Ganze für eine Ini-Datei.

Vielleicht könntest du das Problem umgehen, das du anstelle WriteString, WriteFloat nimmst.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

MmVisual
Beiträge: 1445
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: DefaultFormatSettings.DecimalSeparator

Beitrag von MmVisual »

"Aufzwingen" sollte man einem User schon mal keinen Punkt oder Komma zu nutzen, das geht heutzutage doch viel eleganter:

Code: Alles auswählen

  function GetFloat(ss: string): double;
  var
    bNeg: boolean;
    iPos: integer;
  begin
    bNeg := Copy(ss, 1, 1) = '-';
    if bNeg then
      Delete(ss, 1, 1);
    iPos := 1;
    while iPos <= Length(ss) do
    begin
      if not (ss[iPos] in ['0'..'9', '.', ',']) then
        Delete(ss, iPos, Length(ss) - iPos + 1);
      Inc(iPos);
    end;
    ss := StringReplace(ss, '.', DefaultFormatSettings.DecimalSeparator, []);
    ss := StringReplace(ss, ',', DefaultFormatSettings.DecimalSeparator, []);
    Result := StrToFloatDef(ss, 0);
    if bNeg then
      Result := Result * (-1);
  end


Und auch beim Datum geht das Userfreundlicher und Flexiebler.

Code: Alles auswählen

    dt := StrToDateDef(s, 0);
    if dt = 0 then
    begin
      s := StringReplace(s, '.', DefaultFormatSettings.DateSeparator, [rfReplaceAll]);
      dt := StrToDateDef(s, 0);
      if dt = 0 then
      begin
        s := StringReplace(s, '/', DefaultFormatSettings.DateSeparator, [rfReplaceAll]);
        dt := StrToDateDef(s, 0);
        if dt = 0 then
        begin
          s := StringReplace(s, '/', '.', [rfReplaceAll]);
          s := StringReplace(s, '-', '.', [rfReplaceAll]);
          dt := StrToDateDef(s, 0);
        end;
      end;
    end;   


Also damit zwingt man einem gar nichts auf und die Konvertierung klappt immer. Schließlich programmiert man für einen User, der auch mal sich vertippt (. / ,). Versuche niemals den User zu ändern, sondern mache dein Programm flexibler und damit Benutzerfreundlicher.

Grüße Markus

PS: Meine Software läuft in vielen Ländern der Welt, sogar auch in Kyrillisch und niemand hatte sich bisher über eine Datums oder Zahleneingabe beschwert. Und ich kompiliere für Windows und Linux (32/64 Bit)
Zuletzt geändert von MmVisual am Mi 29. Jun 2016, 17:22, insgesamt 1-mal geändert.
EleLa - Elektronik Lagerverwaltung - www.elela.de

Mathias
Beiträge: 6165
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: DefaultFormatSettings.DecimalSeparator

Beitrag von Mathias »

Also damit zwingt man einem gar nichts auf und die Konvertierung klappt immer.

Was passiert, wen man 1'000'000.00 schreibt ?
Gut Val scheitert hier auch.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

MmVisual
Beiträge: 1445
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: DefaultFormatSettings.DecimalSeparator

Beitrag von MmVisual »

In der Zeile

Code: Alles auswählen

if not (ss[iPos] in ['0'..'9', '.', ',']) then

werden die ' gelöscht, auch alle anderen Tippfehler gleich mit.
EleLa - Elektronik Lagerverwaltung - www.elela.de

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: DefaultFormatSettings.DecimalSeparator

Beitrag von wp_xyz »

@Corpsman: Wenn die Datei auch mit nicht-deutschen Spracheinstellungen gelesen werden soll, musst du die Floats natürlich mit Punkt speichern. TCustomIniFile hat dazu seit einiger Zeit im FPC-trunk englische FormatSettings eingebaut und einen Parameter FormatSettingsActive, mit dem man diese aktivieren kann. Und wenn du die Zahlen selbst speicherst, musst du sie halt per FloatToStr(zahl, PunktSettings) und StrToFloat(text, PunktSettings) umwandlen, wobei PunktSettings eine lokale Kopie der DefaultFormatSettings mit Dezimalpunkt sind. Nur: die Benutzeroberfläche muss bei einem allgemein verwendbaren Programm bei den Ländereinstellungen des Betriebssystems bleiben. (Ich spreche nicht von Programmen, die du alleine verwendest).

@Mathias: Ja, es steht auch in wikipedia (https://de.wikipedia.org/wiki/Dezimaltrennzeichen), dass ihr in der Schweiz bezüglich Dezimal-Punkt/Komma keine einheitlich Meinung habt. Zumindest bei uns wurde das Dezimalkomma definitiv nicht mit dem "Office-Gerümpel" eingeführt, denn als ich zur Schule ging, gab es noch keinen PC und kein Office. Aber diese Diskussion hatten wir schon mal...

@MmVisual: Aber du musst sicherstellen, dass die Zahl keinen Tausendertrenner enthält. Woher weißt du, dass dein User bei einer Eingabe von "1.000" die Zahl 1000 mit deutschem Tausendertrennzeichen oder 1,000 mit englischem Dezimalkomma meint?
Zuletzt geändert von wp_xyz am Mi 29. Jun 2016, 17:43, insgesamt 1-mal geändert.

MmVisual
Beiträge: 1445
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 3.0 FPC 3.2)
CPU-Target: 32/64Bit

Re: DefaultFormatSettings.DecimalSeparator

Beitrag von MmVisual »

In dieses Fettnäpfchen darf er gerne rein tapsen 8)
Wird er nur einmal machen :mrgreen:
EleLa - Elektronik Lagerverwaltung - www.elela.de

Antworten