如何独立于区域设置从 XML 文件中正确读取浮点值?

How to read a floating point value correctly from an XML file independently from regional settings?

我正在从 XML 文件中的一个节点读取浮点属性值 TXMLDocument:

<MyApp_Favorites version="1.0">

...用这个语句:

var
  ThisRootNode: IXMLNode;
  ThisVersion: Single;

// ...

ThisVersion := ThisRootNode.Attributes['version'];
CodeSite.Send('ThisVersion', ThisVersion);

但是,在我的德语系统上,我得到这个版本值:

ThisVersion = 10,00

...在我的区域设置中,逗号“,”被定义为小数点分隔符,而不是点“.”与 XML 文件中一样。但是对于英语语言区域设置——点很可能被定义为小数点分隔符设置——结果将正确为“1.0”。

那么我如何确保独立于区域设置,1.0 的读取值始终相同? (将version值读成string再转成float好像不是很优雅的方法)

浮点数不是版本号的合理格式,舍入错误和缺乏可表示性是主要缺点。考虑使用带整数的记录来定义版本号。

program Project1;
{$APPTYPE CONSOLE}

uses
  SysUtils, StrUtils, Types;
type    
TVersion = record
  private
    procedure Set_AsString(AVersion : string);
    function Get_AsString: String;
  public
    Major: Integer;
    Minor: Integer;
    property AsString: String read Get_AsString write Set_AsString;
end;    

function TVersion.Get_AsString: String;
begin
  Result := Format('%d.%d', [Major, Minor]);
end;

procedure TVersion.Set_AsString(AVersion: string);
var
  split : TStringDynArray;
begin
  split := SplitString(AVersion, '.');
  Major := StrToInt(split[0]);
  Minor := StrToInt(split[1]);
end;

var
  v1, v2 : TVersion;
  s : string;
begin
  v1.Major := 12;
  v1.Minor := 34;
  WriteLn(v1.AsString);

  s := v1.AsString;
  v2.AsString := s;

  WriteLn(v2.AsString);
  ReadLn;
end.

不应将此值视为浮点值。您对二进制浮点类型的表示问题敞开心扉。更好的方法是读取字符串并解析出主要部分和次要部分,然后使用 StrToInt 将它们转换为整数。使用 Pos 拆分字符串本身以找到句点分隔符的位置,或者实际上使用任何 Split 函数。

另一方面,您甚至不清楚是否需要字符串以外的任何格式的此值。那么除了将其作为字符串读取之外,为什么还要费心做任何事情呢?

至于您提出的实际问题,您是否希望使用接受 TFormatSettings 参数的 StrToFloat 的重载。并传入将小数点分隔符设置为 '.'.

的格式设置

使用字符串表示并使用 TFormatSettings.Invariant:

自己进行转换
ThisVersion := StrToFloat(ThisRootNode.Attributes['version'], TFormatSettings.Invariant);