怪异的Delphi运算结果,什么原因造成? 这里我说一下,把ax :=(a*m) shr 21;改为ax :=int64(a*m) shr 21结果就正确了,但是谁能解释一下为什么不加int64会出错? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 因为c++的右移是有符号右移,对应汇编指令是sar而delphi的右移则是无符号右移,对应汇编指令是shr看下俩者反汇编就知道了。 简单的统一方法就内联汇编吧。var a,m,aa:Integer;begin a :=29959314 ; m :=-3; asm push eax push ebx mov eax, a mov ebx, m imul eax, ebx sar eax,21 mov aa, eax pop ebx pop eax end; 2005是对的,Delphi的shr只做逻辑右移,与操作数有符号还是无符号无关,一律做无符号数处理,这在Turbo pascal时代就是一个见于文档的正式特性,与C和C++的>>处理方法不同。之所以产生-43的结果,是编译器在编译时求值(29959314*-3) shr 21;做了不正确的处理(可能是Delphi和CB共享编译器后端造成的BUG,不过后来已经修正了)。 其实原因很简单,因为integer默认只有两个字节,有效值域才正负60000多,你给他一个这么大的数,自然就溢出了,溢出以后能不能保证数字的样子就难说了。而int64默认有8个字节,有效值域达十几位数,不会溢出,自然就对了。 n b ,delphi 默认将整数常数向int32bit靠近,如果要将大常数赋值给变量,加强制转换成int64。在delphi xe5仍然是这样,lazarus是正确的。参考<<delphi陷阱大全>> 至于是2005还是-43,目前我只能说是-43,因为C++是按-43来处理正确,Delphi按2005不是简单结果的错误问题,而是程序崩溃了。(a*m),Delphi当什么处理?(29959314*-3),Delphi又当什么处理?如果处理方式一样,结果应该都一样。为什么会出现两个结果,如果说(a*m)是Integer,哪个地方显式说明了它是Integer,为什么不是int64,或者为什么不是WORD?(29959314*-3)为什么不是Integer,看起来倒更像int64,因为这个,调试了半天。 程序崩溃是你的算法问题,估计你是从C++程序中直接抄过去的算法。“(29959314*-3)为什么不是Integer”,本来就是integer。D7把(29959314*-3) shr 21求值为-43是错误的,这在较新的版本中已经修正了。 把这个值算成-43,程序运行正常,但是-43不是说错误的吗?怎么错误的数字还能正常?C++算出来的也是-43,对于这个值,C++没有做任何处理,直接参与运算。我目前搞不懂,-43既然是错误的,那C++,按道理就是VC6就是错的,那VC6的那个程序怎么能正常运行,我看代码就是移位算出一个结果后,直接返回该值去参与运算。 C++代码如下(VC6编译,也只能它编译,VC2008玩不通,报错)Point Axis::translate(int moveX, int moveY){ long dp = DECIMAL_POINT; Point point; int dx = (moveX == 0) ? 0 : (modulePitch * moveX) >> dp; int dy = (moveY == 0) ? 0 : (modulePitch * moveY) >> dp; point.translate((dx * cos - dy * sin) >> dp, (dx * sin + dy * cos) >> dp); point.translate(origin.x, origin.y); return point;}该函数被以下函数引用//精确版本号int FinderPattern::calcExactVersion(Point * centers, int * angle, int * moduleSize) { BYTE * VersionInfo = new BYTE[18]; Point * points = new Point[18]; Point target; int m=angle[0],n=angle[1]; //右上 --- 版本信息1 Axis axis = Axis(angle, moduleSize[UR], DECIMAL_POINT); //UR m=angle[0];n=angle[1]; axis.setOrigin(centers[UR]); for (int y = 0; y < 6; y++) { for (int x = 0; x < 3; x++) { target = axis.translate(x - 7, y - 3);//此处调用 VersionInfo[x + y * 3] = bitmap[target.x][target.y];//其返回结果直接被数组调用Delphi代码如下:function TAxis.Translate(moveX, moveY: Integer): TPoint;var dp,dx,dy:Integer;begin dp := DECIMAL_POINT; if moveX=0 then dx :=0 else dx := int64(FModulePitch * moveX) shr dp; if moveY=0 then dy :=0 else dy := int64(FModulePitch * moveY) shr dp; //为何要加in64强行转换?????,不加就出错!!!! Result :=Point(0,0); Result.X :=Result.X+ int64(dx * FCos - dy * FSin) shr dp;//同样加int64,否则出错 Result.Y :=Result.Y+ int64(dx * FSin + dy * FCos) shr dp;//同样加int64,否则出错 Result.X :=Result.X+ FOrigin.x; Result.Y :=Result.Y+ FOrigin.y;end;该函数算出target结果后直接被一个数组使用,未做任何处理,C++最后的结果·是在数组内,但是Delphi算出的数字N大(如果不按-43处理),远超出数组范围,程序直接崩溃,代码太繁杂了,算法也看不懂,只能照抄,但是C++似乎看不出对于-43的结果采用将错就错的处理方式。 我说的是“D7把(29959314*-3) shr 21求值为-43是错误的,这在较新的版本中已经修正了。”并没有说C和C++中(29959314*-3) >> 21是错误的。根本原因在于Delphi中的shr并不等同于C的>>。 win98下 indy UDP无法接受广播数据 Delphi如何 用Image显示图片大小是固定的。。而且能看到全图 请教一个ExcelApplication的问题? 呃,不小心写了个比FDIV指令更快的浮点除法函数 一个服务器和多个客户端 怎么让webbrowser每点击一次超级链接就打开一个新的网页? 为什么占用内存这么大? 各位兄弟,急需读写注册表的例子,那位能不能帮帮忙~! 关于在DELPHI中使用SQL_DMO对象库的问题,请高手帮助!! 一个小小小小小问题 DELPHI XE 哪个版本好用,用过的来说下感受,只做普通VCL程序 delphi怎样彻底删除一个件,而不是去回收站?
而delphi的右移则是无符号右移,对应汇编指令是shr
看下俩者反汇编就知道了。
a,m,aa:Integer;
begin
a :=29959314 ;
m :=-3;
asm
push eax
push ebx
mov eax, a
mov ebx, m
imul eax, ebx
sar eax,21
mov aa, eax
pop ebx
pop eax
end;
之所以产生-43的结果,是编译器在编译时求值(29959314*-3) shr 21;做了不正确的处理(可能是Delphi和CB共享编译器后端造成的BUG,不过后来已经修正了)。
而int64默认有8个字节,有效值域达十几位数,不会溢出,自然就对了。
在delphi xe5仍然是这样,lazarus是正确的。参考<<delphi陷阱大全>>
(a*m),Delphi当什么处理?(29959314*-3),Delphi又当什么处理?如果处理方式一样,结果应该都一样。为什么会出现两个结果,如果说(a*m)是Integer,哪个地方显式说明了它是Integer,为什么不是int64,或者为什么不是WORD?(29959314*-3)为什么不是Integer,看起来倒更像int64,因为这个,调试了半天。
Point Axis::translate(int moveX, int moveY)
{
long dp = DECIMAL_POINT;
Point point;
int dx = (moveX == 0) ? 0 : (modulePitch * moveX) >> dp;
int dy = (moveY == 0) ? 0 : (modulePitch * moveY) >> dp;
point.translate((dx * cos - dy * sin) >> dp, (dx * sin + dy * cos) >> dp);
point.translate(origin.x, origin.y); return point;
}该函数被以下函数引用
//精确版本号
int FinderPattern::calcExactVersion(Point * centers, int * angle, int * moduleSize)
{
BYTE * VersionInfo = new BYTE[18];
Point * points = new Point[18];
Point target;
int m=angle[0],n=angle[1];
//右上 --- 版本信息1
Axis axis = Axis(angle, moduleSize[UR], DECIMAL_POINT); //UR
m=angle[0];n=angle[1];
axis.setOrigin(centers[UR]);
for (int y = 0; y < 6; y++) {
for (int x = 0; x < 3; x++) {
target = axis.translate(x - 7, y - 3);//此处调用
VersionInfo[x + y * 3] = bitmap[target.x][target.y];//其返回结果直接被数组调用
Delphi代码如下:
function TAxis.Translate(moveX, moveY: Integer): TPoint;
var
dp,dx,dy:Integer;
begin
dp := DECIMAL_POINT;
if moveX=0 then
dx :=0
else
dx := int64(FModulePitch * moveX) shr dp;
if moveY=0 then
dy :=0
else
dy := int64(FModulePitch * moveY) shr dp; //为何要加in64强行转换?????,不加就出错!!!!
Result :=Point(0,0);
Result.X :=Result.X+ int64(dx * FCos - dy * FSin) shr dp;//同样加int64,否则出错
Result.Y :=Result.Y+ int64(dx * FSin + dy * FCos) shr dp;//同样加int64,否则出错
Result.X :=Result.X+ FOrigin.x;
Result.Y :=Result.Y+ FOrigin.y;
end;该函数算出target结果后直接被一个数组使用,未做任何处理,C++最后的结果·是在数组内,但是Delphi算出的数字N大(如果不按-43处理),远超出数组范围,程序直接崩溃,代码太繁杂了,算法也看不懂,只能照抄,但是C++似乎看不出对于-43的结果采用将错就错的处理方式。