这是运算符 << 的正确实现吗? />>?

发布于 2024-11-17 13:04:03 字数 2153 浏览 2 评论 0 原文

运算符 << 的这些正确实现是吗?和>>用于位移?出于某种原因,在我的运算符/中,它只涉及这两个运算符,某些东西允许愚蠢的跳转,导致除法错误地完成。

    // the value is stored msb in a list of uint8_t
    // so 0x123456 will be stored in the list as {0x12, 0x34, 0x56}
    integer operator<<(size_t shift){
        std::list <uint8_t> out = value;
        for(unsigned int i = 0; i < (shift >> 3); i++)
            out.push_back(0);
        shift &= 7;
        if (shift){
            out.push_front(0);
            std::list <uint8_t>::iterator i = out.begin(), j = out.end();
            i++; j--;
            for(; i != j; i++){
                uint8_t temp = *i >> (8 - shift);
                --i;
                *i += temp;
                i++;
                *i = (uint8_t) (*i << shift);
            }
            uint8_t temp = *i >> (8 - shift);
            i--;
            *i += temp;
            i++;
            *i <<= shift;
        }
        return integer(out);
    }

    integer operator>>(size_t shift){
        std::list <uint8_t> out = value;
        for(unsigned int i = 0; i < (shift >> 3); i++)
            out.pop_back();
        shift &= 7;
        if (shift){
            std::list <uint8_t>::reverse_iterator i = out.rbegin(), j = out.rend();
            j--;
            for(; i != j; i++){
                *i >>= shift;
                i++;
                uint8_t temp = *i << (8 - shift);
                i--;
                *i += temp;
            }
            *j >>= shift;
        }
        return integer(out);
    }

这就是我正在做的事情:

integer(1234567) / integer(6)

inside division algorithm (long division):

numerator       largest multiple of denomiator < numeator

12d687          0c0000
06d687          060000
d687            c000
1687            0c00
0a87            0600
0487            0300
0187            0c        <-- where did this come from??
017b            0180

错误是在显示的操作符之一中还是在其他操作符中?

这是我的整个代码: http://ideone.com/ncq9S

are these correct implementations of the operator<< and >> for bitshifting? for some reason, in my operator/, where it only involves these 2 operators, something is allowing for a silly jump that is causing division to be done incorrectly.

    // the value is stored msb in a list of uint8_t
    // so 0x123456 will be stored in the list as {0x12, 0x34, 0x56}
    integer operator<<(size_t shift){
        std::list <uint8_t> out = value;
        for(unsigned int i = 0; i < (shift >> 3); i++)
            out.push_back(0);
        shift &= 7;
        if (shift){
            out.push_front(0);
            std::list <uint8_t>::iterator i = out.begin(), j = out.end();
            i++; j--;
            for(; i != j; i++){
                uint8_t temp = *i >> (8 - shift);
                --i;
                *i += temp;
                i++;
                *i = (uint8_t) (*i << shift);
            }
            uint8_t temp = *i >> (8 - shift);
            i--;
            *i += temp;
            i++;
            *i <<= shift;
        }
        return integer(out);
    }

    integer operator>>(size_t shift){
        std::list <uint8_t> out = value;
        for(unsigned int i = 0; i < (shift >> 3); i++)
            out.pop_back();
        shift &= 7;
        if (shift){
            std::list <uint8_t>::reverse_iterator i = out.rbegin(), j = out.rend();
            j--;
            for(; i != j; i++){
                *i >>= shift;
                i++;
                uint8_t temp = *i << (8 - shift);
                i--;
                *i += temp;
            }
            *j >>= shift;
        }
        return integer(out);
    }

heres what im doing:

integer(1234567) / integer(6)

inside division algorithm (long division):

numerator       largest multiple of denomiator < numeator

12d687          0c0000
06d687          060000
d687            c000
1687            0c00
0a87            0600
0487            0300
0187            0c        <-- where did this come from??
017b            0180

is the error in one of the operators shown or in some other operator?

heres my entire code: http://ideone.com/ncq9S

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谁的新欢旧爱 2024-11-24 13:04:03
template <typename T>

这真的需要参数化吗?似乎任何移位量都可以存储在 size_t 中,并且在开始其余过程之前隐式或显式转换为 size_t 是一个好主意。

integer operator<<(T shift){

通常,二进制operator函数最好实现为非成员friend。例如,与通用操作数相比,生成 this 指针时考虑的转换较少。我会写friend整数运算符<< (整数 lhs,size_t 移位)

    std::list <uint8_t> out = value;

如果您使用 friend 并按值传递,则此副本是隐式制作的。如果您实际上只是修改一个对象,编译器也可以更轻松地消除它,例如 q = q << 3..

    for(unsigned int i = 0; i < (shift >> 3); i++)// get rid of bytes if shift > 8

在循环条件下要小心。您将运算符应用于高级类型,这可能会导致昂贵的计算(如果 Tinteger,甚至会导致无休止的递归!

    shift &= 7;                                   // shift by less than a byte

此时,如果 shift == 0 最好在此处插入条件return 另外,现在范围确实有限,因此分配给更窄的类型。比 T

    out.push_front(0);                            // extra byte for overflow

这只是必要的 。如果字节非零,可能最好对第一个操作进行特殊情况并使 push_front 成为条件,而不是对最后一个操作进行特殊情况

......嗯,它看起来像 operator>> 。 ; 正在执行更多...跳到那个...

    for(; i != j; i++){
        i++;
        uint8_t temp = *i << (8 - shift);
        i--;
        *i += temp;
    }
    *j >>= shift;

显然循环中缺少 >> 运算符尝试 *i = *i >>另外,我不明白列表是如何变得更短的。

但是,我真的不能 这样做?看看是什么在发布的输出中产生了行为。前导零可能是 operator<< 中无条件 push_front 的结果,但我期望的模式是c6318c、...。您似乎没有重复任何序列,而是随机跳跃。

也许除法代码或类构造函数可以提供线索。

template <typename T>

Does this really need to be parameterized? It would seem that any shift quantity can be stored in a size_t, and converting to size_t implicitly or explicitly would be a good idea before starting the rest of the process.

integer operator<<(T shift){

Usually binary operator functions are best implemented as non-member friends. For example, fewer conversions are considered when producing the this pointer than for generic operands. I'd write friend integer operator<< ( integer lhs, size_t shift ).

    std::list <uint8_t> out = value;

If you use a friend and pass-by-value, then this copy is made implicitly. The compiler also has an easier time eliminating it if you are really just modifying one object, e.g. q = q << 3.

    for(unsigned int i = 0; i < (shift >> 3); i++)// get rid of bytes if shift > 8

Be careful in the loop condition. You're applying an operator to a high-level type, which might cause an expensive computation (or even endless recursion if T is integer!

    shift &= 7;                                   // shift by less than a byte

At this point, if shift == 0 you are done. Best to insert a conditional return here. Also, now the range is really limited, so assign to a narrower type than T.

    out.push_front(0);                            // extra byte for overflow

This is only necessary if the byte will be nonzero. Probably best to special-case the first operation and make the push_front conditional, instead of special-casing the last.

… Hmm, it looks like the operator>> is being exercised more… skipping to that…

    for(; i != j; i++){
        i++;
        uint8_t temp = *i << (8 - shift);
        i--;
        *i += temp;
    }
    *j >>= shift;

Clearly the >> operator is missing from the loop. Try *i = *i >> shift + temp. Also, I don't see how the list ever gets shorter. Is that done in integer::integer( list<…> )?

However, I can't really see what produces the behavior in the posted output. The leading zero is probably a result of the unconditional push_front in operator<<, but the pattern I'd expect is c, 6, 3, 18, c, …. You don't seem to be repeating any sequence, but instead jump randomly.

Maybe the division code, or the class constructor could provide clues.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文