VHDL中实数的比较

VHDL中实数的比较,vhdl,Vhdl,我目前比较两个实数(计算后)的方法是取差并转换为整数,然后比较为0,例如(为了突出问题,示例可能在模拟器中工作) 变量a:real:=0.1; 常数ε:实:=1.0E-5;--不管需要什么样的准确度,但不要太低 a:=a+5.3; 断言a=5.4;——产生间歇性错误 断言整数(a-5.4)=“0”;--如果4.8

我目前比较两个实数(计算后)的方法是取差并转换为整数,然后比较为0,例如(为了突出问题,示例可能在模拟器中工作)

变量a:real:=0.1;
常数ε:实:=1.0E-5;--不管需要什么样的准确度,但不要太低
a:=a+5.3;
断言a=5.4;——产生间歇性错误
断言整数(a-5.4)=“0”;--如果4.8

采用这种方式的原因是,我在编写的测试台中遇到了很多断言错误(比示例代码复杂一点)。我在GHDL模拟器中将这些错误记为浮点错误。有没有更好的方法来比较两个实数,比如使用机器epsilon或任何内置方法?

这个问题对于任何使用“实数”值(又称浮点数)的编程语言都是通用的

在自动测试中比较实数的标准方法是定义一个小值ε。然后检查两个实数之间的绝对差是否小于ε。如果您想编写简明的测试平台,您可以定义自己的过程
assertEqual(x,y,epsilon)

procedure assertEquals(
    x, y    : real; epsilon : real := 1.0E-5;
    message : string               := "";
    level   : severity_level       := error) is
begin
    assert (abs (x - y) < epsilon) report message severity level;
end procedure assertEquals;
procedure assertEquals(
x、 y:real;ε:real:=1.0E-5;
消息:字符串:=“”;
级别:严重性(级别:=错误)为
开始
断言(abs(x-y)
正如@Philippe所指出的,REAL的比较需要一定的裕度来解释有限的精度和最低有效位的累积误差。使用简单的epsilon值是一种常见的方法,但它有一个局限性,即它的值相对于所比较的数字是绝对的。您需要提前知道要比较的预期值,以选择合适的ε

如果需要比较的一组数字涵盖了广泛的数量级,那么最终得到的ε太大,无法正确比较较小的值。在这种情况下,当比较小实数时,您需要一个小的epsilon,而比较大数字时需要一个大的epsilon。这是通过使用解释相对误差的比较来实现的

给出了一个很好的方法概述,该方法允许使用相对误差而不是绝对误差来比较实数。以下函数是VHDL中相对比较的实现:

-- Adapted from: http://floating-point-gui.de/errors/comparison/
function relatively_equal(a, b, epsilon : real) return boolean is
begin
  if a = b then -- Take care of infinities
    return true;
  elsif a * b = 0.0 then -- Either a or b is zero
    return abs(a - b) < epsilon ** 2;
  else -- Relative error
    return abs(a - b) / (abs(a) + abs(b)) < epsilon;
  end if;
end function;

不,它不是每次都像一个符咒一样起作用。。。添加
断言整数(a-5.3)=0;断言(a-5.5)=“0”到您的测试台。。。另请参见卡汉教授关于浮点运算的论文——这可能不是最好的,但www.cs.berkeley.edu/~wkahan/javahert。pdf@brian-drummond这是非常正确的,但它至少消除了本例中的浮点错误,这对于我的easy testbench来说还行,但当然还不够好。更好的方法可能是定义
常量epsilon:real:=0.00001
,然后
断言a-5.4
。但我的问题仍然是,有没有一个好的方法来做到这一点,或者这是最好的;可能允许的偏差应该基于操作数的大小,因为assertEquals(1.0E-6,2.0E-6)不会引发assert。例如,基于单位变化的缩放不应导致不同的比较。一种可能性是允许偏差为
abs(x)+abs(y)
。在IEEE Std 1076-2008-3.1.4.1预定义浮点类型-2002及更早版本-1.0 E38至+1.0 E38之前,实型的大小有不同的规定;5.2.5浮点类型,5.2.5.1概述,符合IEEE标准754-1985或IEEE标准854-1987,最小表示大小为64位。epsilon可以是工具标准版本,也可以是依赖于实现的。另请参阅包float_pkg,了解针对性设计规范和符合合成条件的浮点表示。在软件包math_中,cordic函数使用实际ε值,并带有精度因子。
-- Adapted from: http://floating-point-gui.de/errors/comparison/
function relatively_equal(a, b, epsilon : real) return boolean is
begin
  if a = b then -- Take care of infinities
    return true;
  elsif a * b = 0.0 then -- Either a or b is zero
    return abs(a - b) < epsilon ** 2;
  else -- Relative error
    return abs(a - b) / (abs(a) + abs(b)) < epsilon;
  end if;
end function;
-- Compare for relative equality to three significant digits
-- These are all considered equal while using the same epsilon parameter
assert relatively_equal(1.001, 1.002, 1.0E-3) report "1.001 != 1.002";
assert relatively_equal(100.1, 100.2, 1.0E-3) report "100.1 != 100.2";
assert relatively_equal(1001.0, 1002.0, 1.0E-3) report "1001 != 1002";

-- Compare for relative equality to four significant digits
-- This will raise the assertion
assert relatively_equal(1.001, 1.002, 1.0E-4) report "1.001 != 1.002";