怎么了v:=v shl b?我正在尝试计算mask = 2 n -1 like mask:=1 shl n-1,但是对于整数变量n = 64则失败.
program UInt64Test;
{$APPTYPE CONSOLE}
var
u,v,w:uint64;
const
a=64;
var
b:integer=a;
c:integer=a-1;
begin
u:=1; v:=1; w:=1;
u:=u shl a;
v:=v shl b;
w:=w shl 1 shl c;
writeln(u);
writeln(v);
writeln(w);
readln;
end.
Run Code Online (Sandbox Code Playgroud)
输出:
0
1
0
Run Code Online (Sandbox Code Playgroud)
我怀疑v也是零.
解决了像2 shl (n-1)-1.在这种情况下编译器执行机器shl(不__llshl):
function reciprocal(o:uint64;n:byte=64):uint64; // result * o = 1 (mod 2?)
var
b,m,t:uint64;
begin
result:=0;
t:=2 shl (n-1)-1;
m:=0; b:=1;
while b<>0 do begin
m:=m or b;
if ((o*result) and m)<>1 then result:=result or b;
b:=(b shl 1) and t;
end;
end;
Run Code Online (Sandbox Code Playgroud)
......但是,我不开心.
LU *_* RD 11
操作x shl y和x shr y将x的值向左或向右移位y位,其中(如果x是无符号整数)等于x乘以或除以2 ^ y; 结果与x的类型相同.例如,如果N存储值01101(十进制13),则N shl 1返回11010(十进制26).请注意,y的值以x的类型的大小为基础进行解释.因此,例如,如果x是整数,则x shl 40被解释为x sh18,因为整数是32位而40 mod 32是8.
因此,64位值上的1 shl 64被解释为1 shl 0,其为1.
const
aa = 32;
var
x,y,z : Cardinal;
...
x := 1;
y := 32;
z := x shl aa; // Gives z = 1
z := x shl 32; // Gives z = 1
z := x shl y; // Gives z = 1;
Run Code Online (Sandbox Code Playgroud)
因此,当y是常量时,似乎存在64位值的编译器错误.
注意在64位模式下,1 shl 64导致1.
所以这个bug只存在于32位编译器中.
报道为QC112261 SHL operations by constant fails.
如果你想要的移位操作结果是0,因为ay值> = 64,那么可以使用这个函数:
function ShiftLeft( AValue : UInt64; bits : Integer) : UInt64; inline;
begin
if (bits > 63) then
Result := 0 // Avoid bits being modified modulo 64
else
Result := AValue shl bits;
end;
Run Code Online (Sandbox Code Playgroud)
更新
此编译器错误在版本XE4中得到解决.
| 归档时间: |
|
| 查看次数: |
2099 次 |
| 最近记录: |