为什么 64 位 Delphi 应用程序计算的结果与 32 位构建不同?

2024-04-16

我们最近开始创建应用程序的 64 位版本。在比较测试中,我们发现 64 位版本的计算方式有所不同。我有一个代码示例,演示了两个版本之间的差异。

var
  currPercent, currGross, currCalcValue : Currency;
begin

  currGross := 1182.42;
  currPercent := 1.45;
  currCalcValue := (currGross * (currPercent * StrToCurr('.01')));
  ShowMessage(CurrToStr(currCalcValue));
end;

如果您在 32 位版本中逐步执行此操作,则 currCalcValue 的计算结果为 17.1451,而 64 位版本的计算结果为 17.145。

为什么 64 位版本不计算额外的小数位?所有变量均定义为 4 位十进制货币值。


这是我根据您的代码编写的 SSCCE。请注意控制台应用程序的使用。让生活变得更加简单。

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  currPercent, currGross, currCalcValue : Currency;
begin
  currGross := 1182.42;
  currPercent := 1.45;
  currCalcValue := (currGross * (currPercent * StrToCurr('.01')));
  Writeln(CurrToStr(currCalcValue));
  Readln;
end.

现在查看生成的代码。第一个 32 位:



Project3.dpr.13: currCalcValue := (currGross * (currPercent * StrToCurr('.01')));
0041C409 8D45EC           lea eax,[ebp-$14]
0041C40C BADCC44100       mov edx,$0041c4dc
0041C411 E8A6A2FEFF       call @UStrLAsg
0041C416 8B1504E74100     mov edx,[$0041e704]
0041C41C 8B45EC           mov eax,[ebp-$14]
0041C41F E870AFFFFF       call StrToCurr
0041C424 DF7DE0           fistp qword ptr [ebp-$20]
0041C427 9B               wait 
0041C428 DF2DD83E4200     fild qword ptr [$00423ed8]
0041C42E DF6DE0           fild qword ptr [ebp-$20]
0041C431 DEC9             fmulp st(1)
0041C433 DF2DE03E4200     fild qword ptr [$00423ee0]
0041C439 DEC9             fmulp st(1)
0041C43B D835E4C44100     fdiv dword ptr [$0041c4e4]
0041C441 DF3DE83E4200     fistp qword ptr [$00423ee8]
0041C447 9B               wait 
  

以及 64 位:



Project3.dpr.13: currCalcValue := (currGross * (currPercent * StrToCurr('.01')));
0000000000428A0E 488D4D38         lea rcx,[rbp+$38]
0000000000428A12 488D1513010000   lea rdx,[rel $00000113]
0000000000428A19 E84213FEFF       call @UStrLAsg
0000000000428A1E 488B4D38         mov rcx,[rbp+$38]
0000000000428A22 488B155F480000   mov rdx,[rel $0000485f]
0000000000428A29 E83280FFFF       call StrToCurr
0000000000428A2E 4889C1           mov rcx,rax
0000000000428A31 488B0510E80000   mov rax,[rel $0000e810]
0000000000428A38 48F7E9           imul rcx
0000000000428A3B C7C110270000     mov ecx,$00002710
0000000000428A41 48F7F9           idiv rcx
0000000000428A44 488BC8           mov rcx,rax
0000000000428A47 488B0502E80000   mov rax,[rel $0000e802]
0000000000428A4E 48F7E9           imul rcx
0000000000428A51 C7C110270000     mov ecx,$00002710
0000000000428A57 48F7F9           idiv rcx
0000000000428A5A 488905F7E70000   mov [rel $0000e7f7],rax
  

请注意,32 位代码在 FPU 上执行算术,但 64 位代码使用整数算术执行该算术。这是关键的区别。

在32位代码中,执行以下计算:

  • 将“0.01”转换为货币,即 100,允许 10,000 的定点偏移。
  • 将 14,500 加载到 FPU 中。
  • 乘以 100 得到 1,450,000。
  • 乘以 11,824,200 得到 17,145,090,000,000。
  • 除以 10,000^2 得到 171,450.9。
  • 四舍五入到最接近的整数,得到 171,451。
  • 将其存储在您的货币变量中。因此结果是 17.1451。

现在,在 64 位代码中,情况有些不同。因为我们一直使用64位整数。它看起来像这样:

  • 将“0.01”转换为货币,即 100。
  • 乘以 14,500,即 1,450,000。
  • 除以 10,000,得到 145。
  • 乘以 11,824,200 得到 1,714,509,000。
  • 除以 10,000,即 171,450。呃哦,这里失去了精度。
  • 将其存储在您的货币变量中。因此结果是 17.145。

因此,问题在于 64 位编译器在每个中间步骤都会除以 10,000。大概是为了避免溢出,64 位整数比浮点寄存器更有可能避免溢出。

如果是这样计算的话:

100 * 14,500 * 11,824,200 / 10,000 / 10,000

它会得到正确的答案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 64 位 Delphi 应用程序计算的结果与 32 位构建不同? 的相关文章

  • Delphi:MDI应用程序中的最大化子窗体

    如何最大化仅适合客户区而不适合整个父窗口的子窗口 我不希望子窗口在父窗口的主菜单或其他控件下消失 我有这个代码 procedure WMSIZE var Msg TMessage message WM SIZE procedure TFor
  • Delphi 拼写检查器

    您好 我正在寻找一个与 Delphi 7 2010 一起使用的免费拼写检查器 任何人都可以给我一个指向吗 我想添加我们在 SynProject 编辑器中使用的 HunSpell 库 它包含在该 GPL 工具的源代码中 http synops
  • Delphi:如何在不使用 MAPI 的情况下在 Outlook 中撰写电子邮件?

    在这个问题中我只是问 https stackoverflow com questions 4907143 ideas for storing e mail messages in a delphi client server applica
  • Delphi 远程调试器冻结

    我有运行 Delphi 2007 应用程序的 Windows Server 2008 R2 计算机 Update 当前无法切换 Delphi 版本 我有 Delphi XE 但在进行任何切换之前需要检查超过 300 000 行代码 我遇到了
  • Inno Setup 无法导入 DLL

    我没有运气将 Delphi DLL 导入 Inno Setup Unicode 该DLL有一个简单的过程 procedure Foo stdcall begin end exports Foo 该 DLL 包含在安装程序源中 并添加到文件列
  • 新的 Delphi Rad Studio XE2 中的 FireMonkey (FMX) 包含哪些功能的详细信息?

    我听说德尔福全新 Rad Studio XE2有一个东西叫做火猴这将允许相同的代码构建 Windows 32 Windows 64 和MacOS应用程序 如果这是真的 那么这是巨大的 在哪里可以获得有关 FireMonkey 的技术文档 E
  • 如何将参数传递给 OLE 自动化对象(例如 MS Word)

    这主要是一个Delphi语法相关的问题 调用 OLE 对象的方法时 我需要将参数设置为 True 我需要在Word Automation中设置 这是来自词参考 http support microsoft com kb 285885 en
  • 作为属性的自定义类的数组

    我试图使用自定义类的数组作为我的组件的属性 但问题是这些值没有保存到组件中 这意味着如果我设置值 保存所有内容并再次打开项目 组件的值消失 我的代码如下所示 unit Unit1 interface uses Windows ExtCtrl
  • Delphi 窗体在显示时总是会触发 OnResize 吗?

    如果我创建一个新的 Delphi 表单 挂钩其 OnResize 事件并运行该应用程序 则在显示窗口之前会触发 OnResize 我不知道对于任何窗口来说 这种情况是否总是会发生 对于熟悉 Windows API 的人来说 我已将其追溯到
  • 以与文件大小相同的格式获取类或对象的大小?

    如何从内存中最好地确定类的大小 这是一个可以使用的基本示例类 请注意 这些变量除了用于示例之外没有其他用途 type TMyClass class public fString1 string fString2 string fIntege
  • Move() 从动态字符串数组中插入/删除项目

    使用 System Move 从字符串数组中插入 删除项目并不像从其他简单数据类型数组中插入 删除项目那么容易 问题是 字符串在 Delphi 中是引用计数的 在引用计数数据类型上使用 Move 需要对内部编译器行为有更深入的了解 这里有人
  • 桌面 Delphi 应用程序是否可以通过 Windows 8 认证(使用 Windows 应用程序认证套件)?

    显然 Delphi 任何版本 不支持安全异常处理程序 https forums embarcadero com thread jspa messageID 473469 Visual Studio 中的 SAFESEH 开关 在 Windo
  • 作为属性的类引用

    谷歌对于这类搜索毫无用处 因为你会得到数亿个结果 其中没有一个与特定问题相关 问题很简单 Delphi 中是否可以有类引用属性 如果是这样 怎么办 这是我尝试过的 type TMyObject class end TMyObjectClas
  • 使用 GdiPlus 卸载 DLL 时程序挂起

    我有一个加载 DLL 的应用程序 它使用德尔福 GDI 库 http sourceforge net projects delphigdiplus 该应用程序在卸载 DLL 时挂起 调用免费图书馆 https msdn microsoft
  • delphi分组框标题颜色变化

    我正在使用 BDS 2006 想知道您是否可以使用项目中存在的 XPmanifest 更改组框和单选按钮组标题的颜色 因为它始终是蓝色 唯一的方法是重写 Paint 方法TGroupBox http docwiki embarcadero
  • Winform 没有.NET 框架?

    我必须创建一些表单并将其作为直接 EXE 提供 而不是安装程序 它安装 NET 框架 最终用户对此不满意 他们想要可以直接打开和工作的东西 我知道它可以作为网络完成 但我正在寻找 winforms 吗 请建议哪种工具 技术可以处理这个问题
  • 为应用程序启用主题

    我有一个旧的应用程序 在Win XP中的delphi 7中启动 现在我正在使用delphi 2009 win Vista 如果我开始一个新项目 所有按钮都有一个圆形边缘 但在我的旧应用程序中 所有按钮都有 方形 形状的外观 有什么设置我错过
  • 如何允许表单接受文件删除而不处理 Windows 消息?

    在 Delphi XE 中 我可以允许我的表单接受文件 拖放 但不必处理裸窗口消息吗 您不需要处理消息来实现这一点 你只需要实施IDropTarget并打电话RegisterDragDrop RevokeDragDrop 这真的非常非常简单
  • 如何使用用户输入来寻址 Pascal 中的特定变量(Eval/Exec?)

    我正在尝试在分形程序中做一些非常具体的事情隆起7X http apophysis 7x org 使用的脚本语言是Pascal 该项目是用德尔福写的 https svn code sf net p apophysis7x svn trunk
  • 获取字符、整数和日期字段的字段 oldValue 和 newValue

    我试图只保留表更改的历史记录 所以我想获取一个字段在更改为oldValue之前的值 然后获取它更改为newValue的值 两个值都应转换为字符串 因此 这是该表的一个示例 PartNumber Description 12345 Test

随机推荐

  • 将自定义 CLI 命令移动到另一个文件

    我有一些针对我正在编写的 Flask 应用程序的自定义 cli 命令 我正在按照此处的说明进行操作 命令行界面 http flask pocoo org docs 1 0 cli 问题是我不想把它们全部放在我的 app py 文件中 它会变
  • Git 配置 user.name 不起作用

    我今天安装了适用于 Windows 7 的 Git 我对 Git 还不太了解 我正在关注http git scm com book en Getting Started First Time Git Setup http git scm c
  • 模块化 pow() 中的负幂

    我们如何使用pow在模块化上下文中带有负指数 战俘 x y z 如果存在 z 则 x 和 y 必须是整数类型 并且 y 必须是非负数 gt gt gt pow 11444 357 0 0 gt gt gt pow 11444 357 487
  • 如何在 NLog 中打开和关闭特定级别的日志记录

    我在我的应用程序中使用 NLog 我想创建一个开关来打开和关闭特定的记录器级别
  • 切换 Antd 表单的可见性

    当选择下拉菜单中的选项时 我需要显示某些输入 下拉菜单包含三个选项 血压 体重和温度 当用户选择一个选项时 与该选项相关的输入字段需要可见 而其余的则需要隐藏 例如 当用户选择 血压 时 收缩压和舒张压输入字段需要可见 而温度和体重字段需要
  • 如何在 Linux 中符号链接文件? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我想在Linux 中建立一个符号链接 我编写了这个 Bash 命令 其中第一个路径是我想要链接到的文件夹 第二个路径是编译的源代码 ln
  • 在 iPhone 和 Android 上生成 2D 条形码(例如 QR 码、Data Matrix、PDF417)

    我需要一个图书馆generateiPhone 和 Android 上的 2D 条形码 最好是 WM7 也可能是 j2me 其想法是将信息传输到具有相应扫描仪 解码器 的另一台设备 有哪些好的选择 ZXing http code google
  • 使用 URLField 相对于 TextField 有何优势?

    据我了解 你应该始终使用TextField当您使用 PostgreSQL 数据库时 对于可变长度字符串 因为之间的速度差异TextField and a CharField对于 PostgreSQL 来说可以忽略不计 我对 Django 比
  • API 自动化测试:有没有办法通过内容验证来自动化下载场景?

    我的应用程序中有导出到 Excel 的功能 我有一个场景 执行导出到 Excel 验证 API 响应状态和导出的 Excel 内容 使用 Postman 我可以使用 发送和下载 选项以 xlsx 格式保存导出的 Excel 稍后我可以手动验
  • 如何在 Java 中替换/删除 UTF-8 字符串中的 4(+) 字节字符?

    由于 MySQL 5 1 不支持 4 字节 UTF 8 序列 因此我需要替换 删除这些字符串中的 4 字节序列 我正在寻找一种干净的方法来替换这些字符 Apache 库用问号替换字符对于这种情况来说是可以的 当然 尽管 ASCII 等效的字
  • 与共享数据相比,消息传递的性能损失

    最近有很多关于不使用锁和使用 Erlang 等消息传递方法的讨论 或者关于使用不可变的数据结构 例如函数式编程与 C Java 中的比较 但我关心的是以下几点 AFAIK Erlang 不保证消息传递 消息可能会丢失 如果还要担心消息丢失
  • 压缩从设备获取或从库、iOS 中选择的图像

    在我的应用程序中 用户可以从设备拍摄照片或从库上传照片以将其设置为个人资料照片 现在 当用户完成后 我需要将该图像上传到服务器 通常从设备获取的图像大小为 5 6MB 我需要在上传到服务器之前将其压缩到 25KB 所以我使用以下方法 voi
  • 多标签 OneVsRestClassifier 的网格搜索?

    我正在对多标签数据进行网格搜索 如下所示 imports from sklearn svm import SVC as classifier from sklearn pipeline import Pipeline from sklear
  • Ubuntu 错误“在此 WSL 2 发行版中找不到命令‘docker’。”

    我在 Ubuntu 上运行 WSL 2 在计算机上启动和运行 docker 时遇到一些问题 我安装了 Docker Desktop 并在后台运行 并且还启用了与 Ubuntu 的 WSL 集成 当我尝试运行简单的 docker 命令时 例如
  • 在javascript中将Json时间戳转换为正常日期和时间

    我有一个 Json 时间戳 我想使用 javascript 将其转换为简单的日期时间格式 我需要以下格式的日期和时间 dd mm yyyy hr mn 这是一个示例 json 日期 我希望提取时间戳 timestamp 1326439500
  • 代码编译时方法中函数执行的计数

    我想计算函数 ExecuteAction 在类方法中出现的次数 public class A B public void X ExecuteAction ExecuteAction 得分为 2 因为 ExecuteAction 出现了 2
  • 将文件夹名称添加到输出 Pig Latin

    我在 HDFS 中有下一个目录结构 logs folder 2021 03 01 log1 log2 log3 2021 03 02 log1 log2 2021 03 03 log1 log2 日志由文本数据组成 数据中没有日期 因为它已
  • jQuery Mobile 与 KnockoutJS ListView 问题

    我正在尝试的这个例子 列表视图最终并没有漂亮的外观 谁能建议我做错了什么 这种情况特别发生在 data inset true 上 http jsfiddle net xQ9Uu 1 http jsfiddle net xQ9Uu 1 如果我
  • 立即将已定义的函数应用于所有数据帧[重复]

    这个问题在这里已经有答案了 我已经定义了一个函数 效果很好 尽管如此 我在工作空间中有 20 个数据框 我想要lapply相同的功能 dat1 至 dat20 到目前为止 它看起来像这样 dat1 lt func dat dat1 dat2
  • 为什么 64 位 Delphi 应用程序计算的结果与 32 位构建不同?

    我们最近开始创建应用程序的 64 位版本 在比较测试中 我们发现 64 位版本的计算方式有所不同 我有一个代码示例 演示了两个版本之间的差异 var currPercent currGross currCalcValue Currency