DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: wuliao8
今日帖子: 43
在线用户: 15
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 haggard (haggard) ★☆☆☆☆ -
普通会员
2024/5/22 22:36:40
标题:
64位除法取余bug 浏览:1019
加入我的收藏
楼主: var i: int64;
begin
  i := -5;
  ShowMessage(IntToStr(i mod 8));
end;

以上代码,在64位win执行,得到结果是3; 
i类型为integer时,结果-5正确
win32时,-5正确
除数非2的整数幂时,余数为负数正确
除数使用变量,即便是2的整数幂时,余数也正确。

也就是编译平台为win64,被除数为负的int64变量,且除数为2的整数幂常量时,取余出错
----------------------------------------------
-
作者:
男 haggard (haggard) ★☆☆☆☆ -
普通会员
2024/5/22 22:37:37
1楼: 在delphi11.3,delphi12.1上测试均有此bug
----------------------------------------------
-
作者:
男 asen521 (Asen) ★☆☆☆☆ -
普通会员
2024/5/22 22:46:52
2楼: 记得当时12打了补丁这个bug就修复了的
----------------------------------------------
-没有最好的工具,只有刻苦的程序员!
作者:
男 qiuqiu77 (球球) ▲▲▲▲▲ -
普通会员
2024/5/23 8:46:24
3楼: program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

var
  L: NativeInt;
begin
  try
    var I: Int64 := -5;
    var J: Integer := 8;

    Writeln({$IFDEF CPUX86}'X86'{$ELSE}'X64'{$ENDIF}, sLineBreak);
    Writeln(I mod 8);
    Writeln(I mod NativeInt(8));
    Writeln(I mod Integer(8));
    Writeln(I mod Int64(8));
    Writeln(I mod J);

    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.


X64

3
3
3
3
-5
----------------------------------------------
-
作者:
男 blacktulip (blacktulip) ★☆☆☆☆ -
盒子活跃会员
2024/5/23 9:59:04
4楼: 果然如上,这个bug有点过分了
----------------------------------------------
-
作者:
男 yaochangli (京酱肉丝) ★☆☆☆☆ -
盒子活跃会员
2024/5/23 10:14:53
5楼: 在delphi 10.1 Berlin 上测试,没有问题
----------------------------------------------
我在马路边,看到一分钱,刚要弯腰捡,原来是口痰,我靠...谁吐这么圆!
作者:
男 leisenx (leisen) ▲▲△△△ -
普通会员
2024/5/23 10:49:27
6楼: var x,y,z: int64;
begin
    x := -5;
    y := 8;
    z := x mod y;
    showmessage(inttostr(z));
end;
----------------------------------------------
日月山河
作者:
男 tuesdays (Tuesday) ▲▲▲▲△ -
普通会员
2024/5/23 11:19:31
7楼: 好bug.
此帖子包含附件:
PNG 图像
大小:18.4K
----------------------------------------------
delphi界写python最强, python界写delphi最强. 写自己的代码, 让别人去运行.
作者:
男 tuesdays (Tuesday) ▲▲▲▲△ -
普通会员
2024/5/23 11:22:02
8楼:   program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

var
  L: NativeInt;
  I,J,Z: int64;
begin
  try
    I := -5;
    J := 8;

    Writeln({$IFDEF CPUX86}'X86'{$ELSE}'X64'{$ENDIF}, sLineBreak);
    Writeln(I mod 8);
    Writeln(I mod NativeInt(8));
    Writeln(I mod Integer(8));
    Writeln(I mod Int64(8));
    Writeln(I mod J);
    Z := (I mod J);
    Writeln(Z);
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

--->>>
X64

3
3
3
3
-5
-5
----------------------------------------------
delphi界写python最强, python界写delphi最强. 写自己的代码, 让别人去运行.
作者:
男 souledge (souledge) ★☆☆☆☆ -
普通会员
2024/5/23 11:59:48
7楼: 重点在这里
如果是正数取余8,确实可以和$07进行与运算得出正确结果,但是负数还这么干就直接把符号位给干没了-5 and $07结果就变成3了

要取得正确结果需要用idiv这个支持符号的汇编指令

所以是编译器的问题,生成了错误的汇编指令
此帖子包含附件:
JPEG 图像
大小:653.4K
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2024/5/23 12:10:36
9楼: 12.1 c++的32/64/64x计算结果是-5
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2024/5/23 13:08:36
10楼: 3楼这段代码,估计是delphi前段时间优化取模的问题,编译成win32/win64计算结果和c/c++不一致,
我试了编译成linux,算的结果是-5,c/c++都是-5
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2024/5/23 13:10:12
11楼: 这里有一篇负数取模的文章
https://www.jianshu.com/p/4c4b7f4cc4ee
----------------------------------------------
-
作者:
男 qiuqiu77 (球球) ▲▲▲▲▲ -
普通会员
2024/5/23 14:25:06
12楼: excel 里面=mod(-5, 8) = 3
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2024/5/23 17:03:24
13楼: 这里有篇文
https://blog.csdn.net/weixin_61543874/article/details/122192413

在不同语言,同一个计算表达式,“取模”结果是不同的。我们可以称之为分别叫做正余数 和 负余数

delphi12这版优化的取模计算方法,算法没有统一

既然发现这个问题,自己改一下也很简单的事
----------------------------------------------
-
作者:
男 hectic (村雨Hectic) ▲▲▲▲▲ -
普通会员
2024/5/24 20:51:40
14楼: 无论什么语言上的差异,结果是3肯定是不对的。

12.1 patch1 Int64 win64结果的确是3
----------------------------------------------
-
作者:
男 haggard (haggard) ★☆☆☆☆ -
普通会员
2024/5/25 7:51:54
15楼: program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

var
  I: Int64;
  J, K: Integer;
begin
  I := -5;
  J := I;
  K := SizeOf(I);
  WriteLn(I, '/', K);
  WriteLn({$IFDEF CPUX86}'X86'{$ELSE}'X64'{$ENDIF}, sLineBreak);
  WriteLn(I div SizeOf(I), '...', I mod SizeOf(I));
  WriteLn(I div K, '...', I mod K);
  WriteLn(J div SizeOf(I), '...', J mod SizeOf(I));
  WriteLn(J div K, '...', J mod K);
  ReadLn;
end.
----------
-5/8
X64

0...3
0...-5
0...-5
0...-5
----------------------------------------------
-
作者:
男 haggard (haggard) ★☆☆☆☆ -
普通会员
2024/5/25 7:54:53
16楼: 以上代码和执行结果应该能说明是bug而不是什么语言特性,否则div结果应该是-1
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2024/5/25 8:39:33
17楼: 之前delphi x64取模计算慢,d12做了些优化,快了几倍,估计没测负数取模,下面是取模计算速度讨论的帖子

https://bbs.2ccc.com/topic.asp?topicid=681941

对于我来说,没用过负数取模

我试了下integer的负数取模是对的
----------------------------------------------
-
作者:
男 haggard (haggard) ★☆☆☆☆ -
普通会员
2024/5/25 11:52:37
18楼: 跟楼上那个帖子不是一码事,那里除数特意避开2的整数次幂的。
2的整数次幂应该很早就单独生成汇编代码的,我在delphi7里看到的就不同与普通两个变量相除,当然它没有x64汇编就是了
----------------------------------------------
-
作者:
男 speedbin (speedbin) ★☆☆☆☆ -
盒子活跃会员
2024/5/25 14:43:27
19楼: 13楼说的对,应该是32位计算和64位计算的时候没有保持一致,这里也有一篇文章。

https://10.1pxeye.com/negative-remainder-operation/

不能说是错的,只是定义不同。ubuntu 24 LTS自带计算器结果是:3
此帖子包含附件:
PNG 图像
大小:35.2K
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行70.3125毫秒 RSS