English 中文(简体)
关于没有司库的处理器的大会模拟算法
原标题:
  • 时间:2009-06-02 05:40:12
  •  标签:

我需要实施一个简单宏观,即在一个没有司级操作员的加工商(思索ARM)上找到两个数字。 我可以通过反复的减员来进行分裂,但我不知道这是否最有效率或最容易与外界合作。

任何建议? 法典将更加有用。 这一特殊类别使我们使用了SPARC的子类,因此大多数业务都像这样的:add r1, r2, rdest

这一特定任务要求核对<代码>a mod b = 0,或其余部分为零。 因此,对有效执行的任何背后或建议都是非常受欢迎的。

最佳回答

我不认为你的具体运作是有限的,但我认为,你在假装编码中做了长时间的划分。

dividend = abs(dividend)
divisor = abs(divisor)
if divisor == 0,
    barf
remainder = dividend
next_multiple = divisor

do
    multiple = next_multiple
    next_multiple = left_shift(multiple, 1)
while next_multiple <= remainder && next_multiple > multiple

while multiple >= divisor,
    if multiple <= remainder,
        remainder = remainder - multiple
    multiple = right_shift(multiple, 1)

为了实际计算报价人(或至少计算其绝对值),最后一部分是:

quotient = 0
while multiple >= divisor,
    quotient = left_shift(quotient, 1);
    if multiple <= remainder,
        remainder = remainder - multiple
        quotient = quotient + 1
    multiple = right_shift(multiple, 1)

所有这一切都没有经过测试,而且很可能被 errors弄。

问题回答

我可以考虑两种可能的办法。 由于这是家庭工作,我只提及他们,如果可行,请你工作,以及如何执行:

  1. A/B = 2^(log2(A)-log2(b): 如果你能够拿到这些数值的标识,你可以非常接近这一分数。

  2. 简称: 你们知道,在你能够做到分裂、正确之前,如何进行长期分裂? 因此,教导你的计算机进行双轨长期分立(实际上应该更容易在双手里)。

(编辑:更正第1号,记录司等)

这不能直接回答你的问题,但这是一个有趣的情况。 如果该数字由两个强权制成组合,则可以按操作方式进行。

x % 2^n = x & (2^n - 1)

使用一种或两种循环运行,即<>通常。

更多信息

在你打上或横跨0之前,如 sub背(或如果是负的) b,会很容易执行,尽管几乎肯定不是最有效的。

A/B=Q,因此A=B*Q。 我们知道A &B,我们需要Q。

My idea to add to the mix: Binary search Q. Start with Q=0 & Q=1, perhaps as base cases. Keep doubling until B * Q > A, and then you ve got two bounds (Q and Q/2), so find the correct Q between the two of those. O(log(A/B)), but a bit trickier to implement:

#include <stdio.h>
#include <limits.h>
#include <time.h>

// Signs were too much work.
// A helper for signs is easy from this func, too.
unsigned int div(unsigned int n, unsigned int d)
{
    unsigned int q_top, q_bottom, q_mid;
    if(d == 0)
    {
        // Ouch
        return 0;
    }

    q_top = 1;
    while(q_top * d < n && q_top < (1 << ((sizeof(unsigned int) << 3) - 1)))
    {
        q_top <<= 1;
    }
    if(q_top * d < n)
    {
        q_bottom = q_top;
        q_top = INT_MAX;
    }
    else if(q_top * d == n)
    {
        // Lucky.
        return q_top;
    }
    else
    {
        q_bottom = q_top >> 1;
    }

    while(q_top != q_bottom)
    {
        q_mid = q_bottom + ((q_top - q_bottom) >> 1);
        if(q_mid == q_bottom)
            break;

        if(d * q_mid == n)
            return q_mid;
        if(d * q_mid > n)
            q_top = q_mid;
        else
            q_bottom = q_mid;
    }
    return q_bottom;
}

int single_test(int n, int d)
{
    int a = div(n, d);
    printf("Single test: %u / %u = %u
", n, d, n / d);
    printf(" --> %u
", a);
    printf(" --> %s
", a == n / d ? "PASSED" : "x1b[1;31mFAILEDx1b[0m");
}

int main()
{
    unsigned int checked = 0;
    unsigned int n, d, a;

    single_test(1389797028, 347449257);
    single_test(887858028, 443929014);
    single_test(15, 5);
    single_test(16, 4);
    single_test(17, 4);
    single_test(0xFFFFFFFF, 1);

    srand(time(NULL));

    while(1)
    {
        n = rand();
        d = rand();

        if(d == 0)
            continue;

        a = div(n, d);
        if(n / d == a)
            ++checked;
        else
        {
            printf("
");
            printf("DIVISION FAILED.
");
            printf("%u / %u = %u, but we got %u.
", n, d, n / d, a);
        }

        if((checked & 0xFFFF) == 0)
        {
            printf("
x1b[2K%u checked.", checked);
            fflush(stdout);
        }
    }

    return 0;
}

此外,你还可以通过比照,将每一比一打。 如果B*Q <=A属实,则该比值为1,否则为零。 Proceed MSB->LSB。 (然而,你们需要能够发现B*Q会超支。)

感谢大家的建议!

我开始采用简单的分部分法,反复采用分流算法来实施。 但是,正如史上指出的那样,情况非常容易。 第一种算法:

        .macro mod a, b, r
        mov a, r
divlp:  sub r, b, r
        cmp r, b
        bge divlp
        .endmacro

这与:

mod(a, b){
   int r = a
   while(r >= b){
      r = r - b
   }
   return r
}

模拟可按以下方式计算:

int r = 0;
int q = 0;
for (int i = sizeof(n) * 8 - 1; i >= 0; --i) {
  r <<= 1;
  r |= (n >> i) & 1;
  if (r > d) {
    r -= d;
    q |= 1 << i;
  }
}
return r;

That gives you the remainder, q would be the quotient. If you have bsrl instruction, you can set a better high bound for i, since you can start at the most significant bit only.





相关问题
热门标签