这是运算符 << 的正确实现吗? />>?
运算符 << 的这些正确实现是吗?和>>用于位移?出于某种原因,在我的运算符/中,它只涉及这两个运算符,某些东西允许愚蠢的跳转,导致除法错误地完成。
// 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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这真的需要参数化吗?似乎任何移位量都可以存储在
size_t
中,并且在开始其余过程之前隐式或显式转换为size_t
是一个好主意。通常,二进制
operator
函数最好实现为非成员friend
。例如,与通用操作数相比,生成this
指针时考虑的转换较少。我会写friend整数运算符<< (整数 lhs,size_t 移位)
。如果您使用
friend
并按值传递,则此副本是隐式制作的。如果您实际上只是修改一个对象,编译器也可以更轻松地消除它,例如q = q << 3.
.在循环条件下要小心。您将运算符应用于高级类型,这可能会导致昂贵的计算(如果
T
是integer
,甚至会导致无休止的递归!此时,如果
shift == 0
最好在此处插入条件return
另外,现在范围确实有限,因此分配给更窄的类型。比T
这只是必要的 。如果字节非零,可能最好对第一个操作进行特殊情况并使
push_front
成为条件,而不是对最后一个操作进行特殊情况......嗯,它看起来像
operator>> 。 ;
正在执行更多...跳到那个...显然循环中缺少
>>
运算符尝试*i = *i >>另外,我不明白列表是如何变得更短的。
但是,我真的不能 这样做?看看是什么在发布的输出中产生了行为。前导零可能是
operator<<
中无条件push_front
的结果,但我期望的模式是c
、6
、3
、18
、c
、...。您似乎没有重复任何序列,而是随机跳跃。也许除法代码或类构造函数可以提供线索。
Does this really need to be parameterized? It would seem that any shift quantity can be stored in a
size_t
, and converting tosize_t
implicitly or explicitly would be a good idea before starting the rest of the process.Usually binary
operator
functions are best implemented as non-memberfriend
s. For example, fewer conversions are considered when producing thethis
pointer than for generic operands. I'd writefriend integer operator<< ( integer lhs, size_t shift )
.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
.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
isinteger
!At this point, if
shift == 0
you are done. Best to insert a conditionalreturn
here. Also, now the range is really limited, so assign to a narrower type thanT
.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…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 ininteger::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
inoperator<<
, but the pattern I'd expect isc
,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.