这里我说一下,把ax :=(a*m) shr 21;改为ax :=int64(a*m) shr 21结果就正确了,但是谁能解释一下为什么不加int64会出错?

解决方案 »

  1.   

    因为c++的右移是有符号右移,对应汇编指令是sar
    而delphi的右移则是无符号右移,对应汇编指令是shr
    看下俩者反汇编就知道了。
      

  2.   

    简单的统一方法就内联汇编吧。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;
      

  3.   

    2005是对的,Delphi的shr只做逻辑右移,与操作数有符号还是无符号无关,一律做无符号数处理,这在Turbo pascal时代就是一个见于文档的正式特性,与C和C++的>>处理方法不同。
    之所以产生-43的结果,是编译器在编译时求值(29959314*-3) shr 21;做了不正确的处理(可能是Delphi和CB共享编译器后端造成的BUG,不过后来已经修正了)。
      

  4.   

    其实原因很简单,因为integer默认只有两个字节,有效值域才正负60000多,你给他一个这么大的数,自然就溢出了,溢出以后能不能保证数字的样子就难说了。
    而int64默认有8个字节,有效值域达十几位数,不会溢出,自然就对了。
      

  5.   

    n b ,delphi 默认将整数常数向int32bit靠近,如果要将大常数赋值给变量,加强制转换成int64。
    在delphi xe5仍然是这样,lazarus是正确的。参考<<delphi陷阱大全>>
      

  6.   

    至于是2005还是-43,目前我只能说是-43,因为C++是按-43来处理正确,Delphi按2005不是简单结果的错误问题,而是程序崩溃了。
    (a*m),Delphi当什么处理?(29959314*-3),Delphi又当什么处理?如果处理方式一样,结果应该都一样。为什么会出现两个结果,如果说(a*m)是Integer,哪个地方显式说明了它是Integer,为什么不是int64,或者为什么不是WORD?(29959314*-3)为什么不是Integer,看起来倒更像int64,因为这个,调试了半天。
      

  7.   

    程序崩溃是你的算法问题,估计你是从C++程序中直接抄过去的算法。“(29959314*-3)为什么不是Integer”,本来就是integer。D7把(29959314*-3) shr 21求值为-43是错误的,这在较新的版本中已经修正了。
      

  8.   

    把这个值算成-43,程序运行正常,但是-43不是说错误的吗?怎么错误的数字还能正常?C++算出来的也是-43,对于这个值,C++没有做任何处理,直接参与运算。我目前搞不懂,-43既然是错误的,那C++,按道理就是VC6就是错的,那VC6的那个程序怎么能正常运行,我看代码就是移位算出一个结果后,直接返回该值去参与运算。
      

  9.   

    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的结果采用将错就错的处理方式。
      

  10.   

    我说的是“D7把(29959314*-3) shr 21求值为-43是错误的,这在较新的版本中已经修正了。”并没有说C和C++中(29959314*-3) >> 21是错误的。根本原因在于Delphi中的shr并不等同于C的>>。