首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >灰度码加法

灰度码加法
EN

Stack Overflow用户
提问于 2014-01-04 15:56:29
回答 3查看 5.1K关注 0票数 17

是否有任何已知的方法来计算两个格雷码的加法(也许是减法),而不必将两个格雷码转换成规则二进制码,然后执行二进制加法,然后将结果转换回格雷码?我成功地编写了增量和递减函数,但添加和减法似乎更少文档化,也更难编写。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-01-04 19:57:01

在#6下面的本文件中,有一个串行灰色代码加法算法(直接复制;注意,xor):

代码语言:javascript
复制
procedure add (n: integer; A,B:word; PA,PB:bit;
               var S:word; var PS:bit; var CE, CF:bit);
var i: integer; E, F, T: bit;
begin
   E := PA; F := PB;
   for i:= 0 to n-1 do begin {in parallel, using previous inputs}
       S[i] := (E and F) ⊕ A[i] ⊕ B[i];
       E := (E and (not F)) ⊕ A[i];
       F := ((not E) and F) ⊕ B[i];
   end;
   CE := E; CF := F;
end;

这就增加了灰码字A和B来构成灰码词S,运算子的参数是PA和PB,和奇偶是PS。这在内部传播两个进位,E和F,并产生两个外部进位CE和CF。

不幸的是,它没有说明任何关于减法的内容,但是我想,当你可以编码负数时,你可以使用加法。

票数 11
EN

Stack Overflow用户

发布于 2014-11-06 13:54:05

我接受了@Sebastian Dressler的答案,因为建议的算法确实有效。为了完整起见,我在这里提出了相应的算法C99实现(C++兼容):

代码语言:javascript
复制
// lhs and rhs are encoded as Gray codes
unsigned add_gray(unsigned lhs, unsigned rhs)
{
    // e and f, initialized with the parity of lhs and rhs
    // (0 means even, 1 means odd)
    bool e = __builtin_parity(lhs);
    bool f = __builtin_parity(rhs);

    unsigned res = 0u;
    for (unsigned i = 0u ; i < CHAR_BIT * sizeof(unsigned) ; ++i)
    {
        // Get the ith bit of rhs and  lhs
        bool lhs_i = (lhs >> i) & 1u;
        bool rhs_i = (rhs >> i) & 1u;

        // Copy e and f (see {in parallel} in the original paper)
        bool e_cpy = e;
        bool f_cpy = f;

        // Set the ith bit of res
        unsigned res_i = (e_cpy & f_cpy) ^ lhs_i ^ rhs_i;
        res |= (res_i << i);

        // Update e and f
        e = (e_cpy & (!f_cpy)) ^ lhs_i;
        f = ((!e_cpy) & f_cpy) ^ rhs_i;
    }
    return res;
}

注意:__builtin_parity是一个编译器内蕴(GCC和Clang),它返回整数中集合位数的奇偶校验(如果不存在该内蕴,则有其他方法手工计算)。当一个灰色代码有偶数的集合位时,它是偶数的。该算法还可以改进,但该实现与原算法相当可靠。如果您想了解有关优化实现的详细信息,可以查看代码评审上的这个问答

票数 6
EN

Stack Overflow用户

发布于 2015-04-08 08:09:03

最近,我设计了一种新的算法来添加两个格雷码。不幸的是,它仍然比简单的双转换解决方案慢,也比哈罗德卢卡尔的算法(公认的答案中的算法)慢。但任何解决问题的新方法都是受欢迎的,对吧?

代码语言:javascript
复制
// lhs and rhs are encoded as Gray codes
unsigned add_gray(unsigned lhs, unsigned rhs)
{
    // Highest power of 2 in lhs and rhs
    unsigned lhs_base = hyperfloor(lhs);
    unsigned rhs_base = hyperfloor(rhs);

    if (lhs_base == rhs_base) {
        // If lhs and rhs are equal, return lhs * 2
        if (lhs == rhs) {
            return (lhs << 1u) ^ __builtin_parity(lhs);
        }
        // Else return base*2 + (lhs - base) + (rhs - base)
        return (lhs_base << 1u) ^ add_gray(lhs_base ^ lhs, lhs_base ^ rhs);
    }

    // It's easier to operate from the greatest value
    if (lhs_base < rhs_base) {
        swap(&lhs, &rhs);
        swap(&lhs_base, &rhs_base);
    }

    // Compute lhs + rhs
    if (lhs == lhs_base) {
        return lhs ^ rhs;
    }

    // Compute (lhs - base) + rhs
    unsigned tmp = add_gray(lhs ^ lhs_base, rhs);
    if (hyperfloor(tmp) < lhs_base) {
        // Compute base + (lhs - base) + rhs
        return lhs_base ^ tmp;
    }
    // Here, hyperfloor(lhs) == hyperfloor(tmp)
    // Compute hyperfloor(lhs) * 2 + ((lhs - hyperfloor(lhs)) + rhs) - hyperfloor(lhs)
    return (lhs_base << 1u) ^ (lhs_base ^ tmp);
}

为了正确地工作,该算法使用了以下实用函数:

代码语言:javascript
复制
// Swap two values
void swap(unsigned* a, unsigned* b)
{
    unsigned temp = *a;
    *a = *b;
    *b = temp;
}

// Isolate the most significant bit
unsigned isomsb(unsigned x)
{
    for (unsigned i = 1u ; i <= CHAR_BIT * sizeof(unsigned) / 2u ; i <<= 1u) {
        x |= x >> i;
    }
    return x & ~(x >> 1u);
}

// Return the greatest power of 2 not higher than
// x where x and the power of 2 are encoded in Gray
// code
unsigned hyperfloor(unsigned x)
{
    unsigned msb = isomsb(x);
    return msb | (msb >> 1u);
}

那么,它是如何工作的?

我不得不承认,这是一个相当大的代码墙,作为一个附加的“简单的代码”。它主要基于对Gray代码中的位模式的观察;也就是说,我没有正式证明任何东西,但我还没有找到算法不起作用的情况(如果不考虑溢出,它就不会处理溢出)。以下是用于构造算法的主要观察结果,假设所有内容都是灰色代码:

  • 2*n= (n << 1)⊕奇偶校验(N)
  • 如果a是2的幂,a> b,那么⊕b=a+b
  • 因此,if是2的幂,a< b,然后是⊕b =a,这只有当b<2*a时才能工作。
  • 如果a和b具有相同的超地板但不相等,则a+b=(超地板( a) << 1)⊕((超地板(A)⊕a)+(超地板(B)⊕b))。

基本上,这意味着我们知道如何乘以2,如何将2的幂相加到较小的格雷码中,以及如何从大于2的灰码中减去2的幂,但小于2的下一次方。其他的一切都是技巧,这样我们就可以根据2的等数值或2的幂进行推理。

如果您需要更多的详细信息/信息,您还可以检查这个问答 on Code,它提出了算法的现代C++实现以及一些优化(作为一种奖励,还有一些我们不能在这里得到的MathJax方程:D)。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20923165

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档