加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – Val过程是否使用DecimalSeparator?

发布时间:2020-12-15 04:07:49 所属栏目:大数据 来源:网络整理
导读:StrToFloat使用格式设置的DecimalSeparator. Val似乎只接受包含的字符串.作为小数分隔符. 从_ValExt(Val调用)中的ASM代码看起来它不使用DecimalSeparator. 我可以安全地依赖Val接受实数字符串的事实(?).作为小数分隔符? 解决方法 Val古老,低级,使用起来有
StrToFloat使用格式设置的DecimalSeparator.

Val似乎只接受包含的字符串.作为小数分隔符.

从_ValExt(Val调用)中的ASM代码看起来它不使用DecimalSeparator.

我可以安全地依赖Val接受实数字符串的事实(?).作为小数分隔符?

解决方法

Val古老,低级,使用起来有点棘手.我不建议在用户代码中使用它.而是使用其他例程来扫描值,例如StrToFloat等.如果将StrToFloat与TFormatSettings.Invariant一起使用,则可以确保将点(‘.’)作为小数分隔符.

看看下面的测试代码.在我的德语系统中,小数点分隔符是逗号.所以我尝试了以下方法:

procedure Test;
var
  E: Extended;
  S: Single;
  I: Integer;
  Code: Integer;
begin

  Val('1.234',E,Code);
  if Code = 0 then
    Writeln('1.234 Extended: ',E)
  else
    Writeln('1.234 Extended: Error,code = ',Code);

  Val('1,234',Code);
  if Code = 0 then
    Writeln('1,234 Extended: ',E)
  else
    Writeln('1,234 Extended: Error,Code);

  Val('1.234',S,Code);
  if Code = 0 then
    Writeln('1.234 Single: ',S)
  else
    Writeln('1.234 Single: Error,Code);

  Val('1234',I,Code);
  if Code = 0 then
    Writeln('Integer: ',I)
  else
    Writeln('Integer: Error,Code);

end;

输出是:

1.234 Extended:  1.23400000000000E+0000
1,code = 2
1.234 Single:  1.23399996757507E+0000
Integer: 1234

这清楚地表明Val不使用系统定义的小数分隔符,只接受不变的小数分隔符,即’.’. IMO,System.Val的文档在这里有点误导.

UPDATE

似乎我在代码的“单个部分”中使用了E而不是S.如果你传递一个Single,显然你也得到正确的值,所以我猜编译器(它知道传递了什么)以某种方式将这些信息传递给内部例程.

查看CPU窗口,您可以看到,如果传入浮点类型,则调用System.@ ValExt,它返回FPU堆栈顶部的值(ST(0)).编译器添加适当的代码来存储该值(分别为Extended,Double和Single的FSTP TBYTE,FSTP QWORD或FSTP DWORD).

类似地,对于整数变量(最多32位),调用System.@ValLong,它在EAX中返回一个Integer,并且编译器添加用于以正确大小存储值的适当代码.对于64位整数,调用@ ValInt64,它在EDX:EAX中返回一个值.

FWIW,它还表明Writeln不使用系统定义的小数分隔符.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读