2015-01-08 3 views
2

두 실제 (예 : 계산 후)를 비교하는 현재 방법은 차이를 가져 와서 정수로 변환하고 0과 비교하는 것입니다 (예를 들어 문제를 강조 표시하려면 시뮬레이터에서 예제가 작동 할 수 있음)VHDL의 실제 비교

variable a : real := 0.1; 
constant epsilon : real := 1.0E-5; -- Whatever accuracy needed, not too low though 
a := a + 5.3; 

assert a = 5.4;    -- Yields intermitent errors 
assert integer(a - 5.4) = '0'; -- Erroneous if 4.8 < a < 5.9 due to cast rounding 
assert abs(a - 5.4) < epsilon; -- Will work everytime, but seems a bit forced 

이 이유는 필자가 작성한 테스트 벤치에서 많은 어설 션 오류가 발생했기 때문입니다. 나는 GHDL 시뮬레이터에서 이러한 오류를 부동 소수점 오류로 간주했다. 서로 기계적으로 엡실론을 사용하거나 메서드를 빌드하는 것과 같은 두 가지 실제 결과를 비교할 수있는 더 좋은 방법이 있습니까?

+1

아니,이 정수를 주장하는 '추가 ... 매력 때마다처럼 작동하지 않습니다 (A-5.3) = 0; assert (a-5.5) = '0';'을 테스트 벤치로 가져옴 ... Prof Kahan의 부동 소수점에 관한 논문을 참고하십시오 - 이것은 최고의 것이 아니지만 www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf –

+0

@ brian-drummond 그건 사실이지만 적어도이 경우에는 부동 소수점 오류를 없애 버리고 내 쉬운 테스트 벤치에서는 괜찮지 만 충분히 좋지는 않습니다. 보다 나은 접근법은 아마도'constant ε : real : = 0.00001'을 정의한 다음''- 5.4 <ε '을 선언하는 것입니다. 그러나 나의 질문은 아직도 남아있다, 이것을하는 좋은 방법 있는가 또는 이것 최고인가? – Johan

+2

assert abs (a-5.4) ε; –

답변

1

이 질문은 "실제"값 (a.k.a. 부동 소수점 숫자)을 사용하는 프로그래밍 언어의 일반적인 내용입니다.

자동 테스트에서 실제 값을 비교하는 표준 방법은 작은 값의 엡실론을 정의하는 것입니다. 그런 다음 두 실제의 절대 차가 엡실론보다 작은 지 확인하십시오. 간결한 테스트 벤치를 작성하려는 경우 자신의 프로 시저 assertEqual(x,y, epsilon)을 정의 할 수 있습니다.

@Philippe로 나타낸 바와
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; 
+1

아마도 assertEquals (1.0E-6, 2.0E-6)가 어설 션을 발생시키지 않기 때문에 허용되는 편차는 피연산자의 크기를 기반으로해야합니다. 예를 들어, 단위 변경을 기준으로 한 스케일링은 다른 비교를해서는 안됩니다. 하나의 가능성은 'abs (x) + abs (y)'의 비율로 편차를 허용하는 것입니다. –

+0

real 유형의 크기는 IEEE Std 1076-2008 이전에 다르게 지정됩니다. - 3.1.4.1 미리 정의 된 부동 소수점 유형 -2002 이하 - 1.0 E38 ~ + 1.0 E38 포함. 5.2.5 부동 소수점 유형, 5.2.5.1 일반은 IEEE Std 754-1985 또는 IEEE Std 854-1987을 따르며 최소 표현 크기는 64 비트입니다.엡실론은 도구 표준 버전이거나 구현에 따라 달라질 수 있습니다. 디자인 사양 대상 및 합성 대상 부동 소수점 표현에 대해서는 float_pkg 패키지를 참조하십시오. math_real 패키지에서 엡실론 값은 정밀도 요소가있는 코드 함수에서 사용됩니다. – user1155120

3

는 실수의 비교는 제한된 정밀도 및 최하위 비트의 누적 오차를 설명하기 위해 일부 마진을 필요로한다. 단순한 엡실론 값을 사용하는 것이 일반적인 방법이지만 비교되는 숫자와 관련하여 그 값이 절대적이라는 한계가 있습니다. 적절한 엡실론을 선택하기 위해 비교할 예상 값을 미리 알아야합니다.

비교해야 할 숫자 세트가 넓은 범위를 다루는 경우 작은 값을 제대로 비교하기에는 너무 큰 엡실론으로 끝납니다. 이 상황에서 작은 실수를 비교할 때는 작은 엡실론을, 큰 숫자의 경우 큰 엡실론을 원할 것입니다. 이것은 상대적 오류를 설명하는 비교를 사용하여 수행됩니다.

This page은 절대 오류가 아닌 상대 오류를 사용하여 실수를 비교할 수있는 방법에 대한 개요를 제공합니다. 여기서, ε 파라미터 상대 어떤지를 비교 유효 숫자의 개수를 특정하는 부분이다

-- 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; 

다음 함수는 VHDL의 상대적인 비교의 구현이다.

-- 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";