Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi中ABS函数失效_Delphi - Fatal编程技术网

Delphi中ABS函数失效

Delphi中ABS函数失效,delphi,Delphi,在Delphi6或Delphi 2010中,声明两个Currency类型的变量(vtemp1、vtemp2),并为它们提供一个0.09的值。 将其中一个变量嵌入ABS函数,并将其与另一个进行比较。 作为编译器,您会期望比较产生积极的结果 手表显示的abs(vtemp1)和vtemp2的值相同。 奇怪的是if语句失败了 注: -只有在处理 数字0.09(尝试其他几个近似值显示正常结果) -将变量声明为Double而不是currency,问题就不存在了 我认为原因是类型转换Abs()函数返回real

在Delphi6或Delphi 2010中,声明两个Currency类型的变量(vtemp1、vtemp2),并为它们提供一个0.09的值。 将其中一个变量嵌入ABS函数,并将其与另一个进行比较。 作为编译器,您会期望比较产生积极的结果 手表显示的abs(vtemp1)和vtemp2的值相同。 奇怪的是if语句失败了

注: -只有在处理 数字0.09(尝试其他几个近似值显示正常结果)
-将变量声明为Double而不是currency,问题就不存在了

我认为原因是类型转换
Abs()
函数返回
real
结果,因此
currency
变量强制转换为
real
。查看文档:

Currency是一种定点数据类型,可以最大限度地减少数据中的舍入误差 货币计算。在Win32平台上,它存储为缩放的 隐式包含最后四个有效数字的64位整数 表示小数位的。当与中的其他实类型混合时 赋值和表达式、货币值将自动分割 或者乘以10000

因此,货币是固定的,而实际货币是浮点数。 您的问题的示例代码是:

program Project3;
{$APPTYPE CONSOLE}

const VALUE = 0.09;
var a,b  : currency;
begin
    a := VALUE;
    b := VALUE;

    if a = Abs(b) then writeln('equal')
    else writeln('not equal', a - Abs(b));

    readln;
end.
由于类型转换,产生不相等的结果

编译器监视为abs(vtemp1)和vtemp2显示相同的值

尝试添加
x:real
,然后调用
x:=abs(b)
,将
x
添加到手表列表中,选择它并按
编辑手表
,然后选择浮点<代码>X变为
0.899…967

不仅
0.09
值产生这样的结果。您可以尝试使用此代码检查:

    for i := 0 to 10000 do begin
        a := a + 0.001;
        b := a;
        if a <> abs(b) then writeln('not equal', a);
    end;

稍微澄清一下。如果比较浮点值,则会出现“问题”:

var
  A: Currency;

begin
  A:= 0.09;
  Assert(A = Abs(A));
end;
var
  A, B: Currency;
begin
  A:= 0.09;
  B:= Abs(A);
  Assert(A = B);
end;
这是因为
Abs(A)
返回一个浮点值,并且
A=Abs(A)
实现为浮点比较

如果比较货币价值,我无法复制:

var
  A: Currency;

begin
  A:= 0.09;
  Assert(A = Abs(A));
end;
var
  A, B: Currency;
begin
  A:= 0.09;
  B:= Abs(A);
  Assert(A = B);
end;
但是第二个示例也是一个潜在的错误,因为
B:=Abs(a)
内部是一个浮点除法/乘法10000,取整为货币(int64),并且取决于FPU取整模式



我创建了一个,它被打开了。

我刚刚发现Delphi XE2Abs函数不会使货币类型过载。

这些是abs支持的唯一类型

  • 函数Abs(X:):实数;超载
  • 函数Abs(X:):Int64;超载
  • 函数Abs(X:):整数;超载
使用来自“数学”或类似语言的
SameValue
。货币不是浮点type@valexhome根据文献记载,货币是固定的。至少在当前版本中:@Serg-Abs(Currency)可能是,编译器生成一个FCOMPP来将值与D2007进行比较。顺便说一句,我可以复制它。感谢您的及时回复,正如您所指出的,我使用了类似的解决方法来避免这个问题。尽管这个解释有道理,但这不被认为是Delphi IDE中的一个bug还是编译器本身的bug吗?@Khatchig-正式地说,这不是一个bug,而是一个记录在案的行为(“按设计”)。我同意这是一个不好的行为,Embarcadero可以修复它(使
Abs(货币)
返回货币类型,而不是浮动货币)。