2017-04-21 19 views
0

Burnikel 및 Ziegler 부서의 에펠 구현, 특히 "알고리즘 2 - 3n/2n"의 문제점이 무엇인지 알려주는 또 다른 눈이 필요합니다. 에펠 기능이 아래에 나와 있습니다. "현재와 같은"유형은 ARRAYED_LIST [NATURAL_8]입니다. 즉, 구현시 8 비트 값을 포함하는 숫자 (즉 팔다리)가 사용되므로 숫자는 기본 256 자입니다. 실패한 호출에 대한 수동 추적이 수행됩니다. 죄송합니다 인수가 너무 커서 짧은 값으로 오류를 재현 할 수 없습니다. 실행이 경우 3b 단계를 수행하십시오.Burnikel 및 Ziegler 알고리즘 2의 에펠 구현시 오류가 발생했습니다.

여기에 문제가 있습니다. 알고리즘은 5 단계에서 문제가없는 것으로 보입니다. 여기서 나머지 "r"은 제수보다 많은 자릿수로 끝납니다. 나는 그 오류가 아마도 "베타^n - 1"이라는 값을 공급한다고 가정 한`ones '를 호출하는 것으로서 3b 단계에 있다고 믿는다. . (어쩌면 내가

여기

에펠 코드 B & Z의 "베타^N"표기법을 이해하지 : 추적에서

three_by_two_divide (a, a3, b: like Current): TUPLE [quot, rem: like Current] 
     -- Called by `two_by_one_divide'. It has similar structure as 
     -- `div_three_halves_by_two_halfs', but the arguments to this 
     -- function have type {JJ_BIG_NATURAL} instead of like `digit'. 
     -- See Burnikel & Zieler, "Fast Recursive Division", pp 4-8, 
     -- Algorithm 2. 
    require 
     n_not_odd: b.count >= div_limit and b.count \\ 2 = 0 
     b_has_2n_digits: b.count = a3.count * 2 
     a_has_2n_digits: a.count = a3.count * 2 
    local 
     n: INTEGER 
     a1, a2: like Current 
     b1, b2: like Current 
     tup: TUPLE [quot, rem: like Current] 
     q, q1, q2, r, r1: like Current 
     c, d: like Current 
    do 
     n := b.count // 2 
      -- 1) Split `a' 
     a1 := new_sub_number (n + 1, a.count, a) 
     a2 := new_sub_number (1, n.max (1), a) 
      -- 2) Split `b'. 
     b1 := new_sub_number (n + 1, b.count, b) 
     b2 := new_sub_number (1, n.max (1), b) 
      -- 3) Distinguish cases. 
     if a1 < b1 then 
       -- 3a) compute Q = floor ([A1,A2]/B1 with remainder. 
      if b1.count < div_limit then 
       tup := school_divide (a, b1) 
      else 
       tup := two_by_one_divide (a, b1) 
      end 
      q := tup.quot 
      r1 := tup.rem 
     else 
       -- 3b) Q = beta^n - 1 and ... 
      q := ones (n) 
       -- ... R1 = [A1,A2] - [B1,0] + [0,B1] = [A1,A2] - QB1. 
      r1 := a + b1 
      if n > 1 then 
       b1.shift_left (n) 
      else 
       b1.bit_shift_left (zero_digit.bit_count // 2) 
      end 
      r1.subtract (b1) 
     end 
      -- 4) D = Q * B2 
     d := q * b2 
      -- 5) R1 * B^n + A3 - D. (The paper says "a4".) 
     r1.shift_left (n) 
     r := r1 + a3 - d 
      -- 6) As long as R < 0, repeat 
     from 
     until not r.is_negative 
     loop 
      r := r + b 
      q.decrement 
     end 
     check 
      remainder_small_enough: r.count <= b.count 
       -- because remainder must be less than divisor. 
     end 
     Result := [q, r] 
    ensure 
    -- n_digit_remainder: Result.rem.count = b.count // 2 
     quotient_has_correct_count: Result.quot.count <= b.count // 2 
    end 

, 내가 나쁜 생각 라인에있는 화살표 점,하지만 난 그것으로 무엇을 해야할지 모르겠어요 여기에 추적입니다 :.. 나는이 오래 알고

three_by_two_divide (a = [227,26,41,95,169,93,135,110], 
        a3 = [92,164,19,39], 
        b = [161,167,158,41,164,0,0,0]) 

    n := b.count // 2 = 4 
     -- 1) Split `a'. 
    a1 := new_sub_number (n + 1, a.count, a) = [227,26,41,95] 
    a2 := new_sub_number (1, n.max (1), a) = [169,93,135,110] 
     -- 2) Split `b'. 
    b1 := new_sub_number (n + 1, b.count, b) = [161,167,158,41] 
    b2 := new_sub_number (1, n.max (1), b) = [164,0,0,0] 
     -- 3b) Q = beta^n -1 and ... 
--> q := ones (4) = [255,255,255,255]   <-- Is this the error? 
     -- ... R1 = [A1,A2] - [B1,0] + [0,B1]. 
    r1 := a + b1 = [227,26,41,96,75,5,37,151] 
    b1.shift_left (n) = [161,167,158,41,0,0,0,0]       
    r1.subtract (b1) = [65,114,139,55,75,5,37,151] 
    d := q * b2 = [163,255,255,255,92,0,0,0] 
    r1.shift_left (n) = [227,25,135,184,172,220,37,151,0,0,0,0] -- too big! 
    r := r1 + a3 - d -= [227,25,135,184,8,220,37,152,0,164,19,39] -- too big! 

,하지만 어떤 도움이 감사

답변

0

내가 r1 = [65,114,139,55,75,5,37,151] 확인하는 것이 좋습니다 것이 내가 여전히 r1.shift_left (n)을하기 전에 동일합니다.

  1. d := q * b2이있는 동안은 안 r1에 영향을 미치는 두 가지 옵션이 있습니다. 대체로 별칭이 있습니다. 즉 r1에는 업데이트되는 다른 변수와 별칭이 지정되어 있으며이 별칭을 제거해야합니다.
  2. r1d := q * b2 이후에 여전히 동일합니다. 문제는 shift_left으로 일부 데이터를 (다시) 초기화하지 않아야하거나 그렇지 않아야하는 글로벌 데이터를 사용하는 것입니다.
+0

감사합니다. 알렉산더, 별칭 및 전체 데이터 없음. 나는 'ones'에 대한 호출을 피함으로써이 문제를 해결했다고 생각한다. Burnikel & Ziegler는 A를 B로 나누면 "A = Bβ^n이면 new_a : = A - B를 얻고 몫이 1로 시작한다는 것을 기억하십시오.이 시점에서 A는 B보다 작으므로 B & Z가 진행하는 것처럼 진행하십시오. 나는 새로운 질문에 게시 할 또 다른 문제가 있습니다. 감사. – jjj

+0

'[65,114,139,55,75,5,37,151]'이 (가) r1.shift_left (n)을 사용하여 4 자리 숫자만큼 왼쪽으로 시프트하는 것이 실제로 [227,25,135,184,172,2203711510000 ]'. 그러한 행동을 설명 할 수 있다면 구현을 이해하는 데 도움이됩니다. –