c++ - 这是 operator<</>> 的正确实现吗?

标签 c++ math operator-overloading bitwise-operators bit-shift

这些运算符<< 和>> 的位移是否正确?出于某种原因,在我的 operator/中,它只涉及这 2 个运算符,某些东西允许愚蠢的跳转,导致除法不正确。

    // 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

最佳答案

template <typename T>

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

integer operator<<(T shift){

通常是二进制 operator函数最好作为非成员实现 friend秒。例如,生成 this 时考虑的转化次数较少指针而不是通用操作数。我会写 friend integer operator<< ( integer lhs, size_t shift ) .

    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 >> shift + temp .另外,我看不出列表是如何变短的。是在 integer::integer( list<…> ) 中完成的吗? ?

但是,我真的看不出是什么导致了发布的输出中的行为。前导零可能是无条件 push_front 的结果在 operator<< ,但我期望的模式是 c , 6 , 3 , 18 , c ,……你似乎没有重复任何序列,而是随机跳跃。

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

关于c++ - 这是 operator<</>> 的正确实现吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6488790/

相关文章:

c++ - 如何为 Hana 序列编写 for 循环?

c++ - Atlsd.lib 库错误

c++ - 使用模板重载 + 运算符

c++ - 使用 std::copy 时, vector 上的 ostream 重载会引发错误

c++ - 从结构指针调用重载的运算符函数

c++ - 如何将 vector 变量传递给函数?

c++ - C++ 中的异步线程

JavaScript - 欧拉项目#5——效率

c++ - 我应该保留此函数以查找第n个素数还是可以对其进行优化?

math - float 学坏了吗?