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 ????? 没天理啊!
-5(二进制11111111111111111111111111111011)是负数,右移1位成01111111111111111111111111111101
编译器会按-5是负数而把符号位置1,因此编译后直接保存为-3(11111111111111111111111111111101)的常量
而(y shr 1)会编译为汇编码(shr edi,1)这样的,按照shr的定义,右移后高位是补0的,不会因为是负数而置符号位,所以结果就是01111111111111111111111111111101,这个是没问题的。
有符号数的移位,如果你要用shr,需要自己处理符号位
代码里运算时,那就要程序自己处理了
比如:
if (是正数)
xx := x shr 1
else
xx := (x shr 1) or $80000000
(x shr 1) or $80000000 也不是正确的结果......... 你说这是没问题的,为什么在c,c++,甚至VB里都可以得到正确结果?其它编译器都可以负值变值 shr,delphi不行?网上也没查到相关文章说明。 我不是要讨论自己怎么写函数处理,我是觉得delphi走了这么多年,从辉煌到末落...居然还有这么个BUG....
实在想用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都没问题,没有你所谓的“正确结果”
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;
不知道说清楚没有
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;发现了点问题,修正