关与shr运算符有bug???

rcy 2009-06-19 05:35:12

var x, y: Integer;
begin
x := 5;
y := -5;
ShowMessage(IntToStr(x shr 1) + ' =====> ' + IntToStr(5 shr 1) + ' , '
+ IntToStr(y shr 1) + ' =====> ' + IntToStr(-5 shr 1));
end;

下面是运行结果.
---------------------------
Project1
---------------------------
2 =====> 2 , 2147483645 =====> -3
---------------------------
OK
---------------------------


在需要高效运算的地方居然不能对负值变量shr ????? 没天理啊!
...全文
122 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
Seamour 2009-06-22
  • 打赏
  • 举报
回复
在delphi中shr运算符只会编译成x86指令集的shr,而不会对有符号整型编译成sar。这不是bug,而是向前兼容,turbo pascal/borland pascal中就一直如此,free pascal同样不会得到sar的结果
实在想用sar的话就内嵌汇编吧

另外,根据c99标准(n1362.pdf)中对>>运算符语义的规定:
6.5.7
...
5 The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type
or if E1 has a signed type and a nonnegative value, the value of the result is the integral
part of the quotient of E1 /2E2. If E1 has a signed type and a negative value, the resulting
value is implementation-defined.
也就是说,在c语言中,>>对有符号负整数的运算结果是 implementation-defined 行为,编译器编译成shr还是sar都没问题,没有你所谓的“正确结果”
xiaowei_001 2009-06-22
  • 打赏
  • 举报
回复


var
Tmp_Int: Byte;
begin
Tmp_Int := 254; //二进制编码:1111 1110
ShowMessage(IntToStr(Tmp_Int shr 1)); //"127"
end;

var
Tmp_Int: ShortInt; //-128 - 127
begin
Tmp_Int := -1; //二进制编码:1111 1110 ;;;1的二进制编码:0000 0001;; -1的编码是在1的基础上首位置1,符号位.后面几位按位补码即1111 1110
ShowMessage(IntToStr(Byte(Tmp_Int) shr 1)); //"127"
end;



发现了点问题,修正
xiaowei_001 2009-06-22
  • 打赏
  • 举报
回复
举个例子,为了方便数据类型用的是Byte

var
Tmp_Int: Byte;
begin
Tmp_Int := 254; //二进制编码:1111 1110
ShowMessage(IntToStr(Tmp_Int shr 1)); //"127"
end;

var
Tmp_Int: ShortInt; //-128 - 127
begin
Tmp_Int := -1; //二进制编码:1111 1110 ;;;1的二进制编码:0000 0001;; -1的编码是在1的基础上首位置1,符号位.后面几位按位补码即1111 1110
ShowMessage(IntToStr(Tmp_Int shr 1)); //"127"
end;


不知道说清楚没有
xiaowei_001 2009-06-22
  • 打赏
  • 举报
回复
楼主要是对二进制编码有所了解,就不会提这个问题了,
rcy 2009-06-21
  • 打赏
  • 举报
回复

(x shr 1) or $80000000 也不是正确的结果.........

你说这是没问题的,为什么在c,c++,甚至VB里都可以得到正确结果?其它编译器都可以负值变值 shr,delphi不行?网上也没查到相关文章说明。

我不是要讨论自己怎么写函数处理,我是觉得delphi走了这么多年,从辉煌到末落...居然还有这么个BUG....


lbx408 2009-06-19
  • 打赏
  • 举报
回复
补充一下,delphi里没有算术右移sar,所以估计是delphi编译(-5 shr 1)时会自动按(-5 sar 1)来算常量值
代码里运算时,那就要程序自己处理了
比如:
if (是正数)
xx := x shr 1
else
xx := (x shr 1) or $80000000
lbx408 2009-06-19
  • 打赏
  • 举报
回复
这不是shr的问题,是编译器优化的结果。编译器处理(-5 shr 1)会当成一个常量来处理,会先算出 -5 shr 1的值作为常数保存,而不会在运行时计算
-5(二进制11111111111111111111111111111011)是负数,右移1位成01111111111111111111111111111101
编译器会按-5是负数而把符号位置1,因此编译后直接保存为-3(11111111111111111111111111111101)的常量
而(y shr 1)会编译为汇编码(shr edi,1)这样的,按照shr的定义,右移后高位是补0的,不会因为是负数而置符号位,所以结果就是01111111111111111111111111111101,这个是没问题的。
有符号数的移位,如果你要用shr,需要自己处理符号位

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧