0
我需要另一组眼睛来告诉我Burnikel和Ziegler的部门的Eiffel实现有什么问题,特别是“算法2 - 3n/2n”。埃菲尔功能如下所示。类似“Current”的类型是ARRAYED_LIST [NATURAL_8]。换句话说,该实现使用包含8位值的数字(即分支),因此数字以256为基数。以下是一个失败呼叫的手动追踪。 (对不起,参数非常大,但我无法用较短的值重现此错误。)在这种情况下,执行步骤在步骤3b之后。Burnikel和Ziegler算法的Eiffel实现中的错误2
这是问题所在。该算法对第5步似乎没有问题,其余部分“r”以除数后的数字结束。我相信这个错误是在步骤3b中,也许是调用了“假设”提供“Beta^n - 1”值的'ones'。 (也许我不明白乙&个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!
我知道这是很长,但任何帮助表示赞赏
谢谢亚历山大,没有别名,也没有全球数据。我想我已经通过避免调用'ones'来解决这个问题。 Burnikel&Ziegler认为A由B划分,“让A =Bβ^ n,得到一个new_a:= A-B并记住商以1开始。此时,A小于B,所以按照B&Z的说法进行。我有另一个问题,但我会在一个新问题中发帖。谢谢。 – jjj
我真的不知道如何将'[65,114,139,55,75,5,37,151]'左移4位数'与'r1.shift_left(n)'给出'[227,25,135,184,172,220,37,151,0,0,0,0 ]'。如果你能解释这样的行为,它将有助于理解实现。 –