为什么 GDB 计算浮点运算的方式与 C++ 不同?

2024-01-07

我在尝试处理浮点算术问题时遇到了一些令人困惑的事情。

首先,代码。我将问题的本质提炼到这个例子中:

#include <iostream>
#include <iomanip>

using namespace std;
typedef union {long long ll; double d;} bindouble;

int main(int argc, char** argv) {
    bindouble y, z, tau, xinum, xiden;
    y.d = 1.0d;
    z.ll = 0x3fc5f8e2f0686eee; // double 0.17165791262311053
    tau.ll = 0x3fab51c5e0bf9ef7; // double 0.053358253178712838
    // xinum = double 0.16249854626123722 (0x3fc4ccc09aeb769a)
    xinum.d = y.d * (z.d - tau.d) - tau.d * (z.d - 1);
    // xiden = double 0.16249854626123725 (0x3fc4ccc09aeb769b)
    xiden.d = z.d * (1 - tau.d);
    cout << hex << xinum.ll << endl << xiden.ll << endl;
}

xinum and xiden应该具有相同的值(当y == 1),但由于浮点舍入误差,它们没有。我明白了那部分。

当我通过 GDB 运行这段代码(实际上是我真正的程序)来追踪差异时,问题就出现了。如果我使用 GDB 重现代码中完成的评估,它会为 xiden 提供不同的结果:

$ gdb mathtest
GNU gdb (Gentoo 7.5 p1) 7.5
...
This GDB was configured as "x86_64-pc-linux-gnu".
...
(gdb) break 16
Breakpoint 1 at 0x4008ef: file mathtest.cpp, line 16.
(gdb) run
Starting program: /home/diazona/tmp/mathtest 
...
Breakpoint 1, main (argc=1, argv=0x7fffffffd5f8) at mathtest.cpp:16
16          cout << hex << xinum.ll << endl << xiden.ll << endl;
(gdb) print xiden.d
$1 = 0.16249854626123725
(gdb) print z.d * (1 - tau.d)
$2 = 0.16249854626123722

你会注意到,如果我要求 GDB 计算z.d * (1 - tau.d),它给出 0.16249854626123722 (0x3fc4ccc09aeb769a),而在程序中计算相同内容的实际 C++ 代码给出 0.16249854626123725 (0x3fc4ccc09aeb769b)。因此 GDB 必须使用不同的浮点运算评估模型。谁能进一步阐明这一点? GDB 的评估与我的处理器的评估有何不同?

我确实看过这个相关问题 https://stackoverflow.com/questions/5122570/why-does-gdb-evaluate-sqrt3-to-0询问GDB评估sqrt(3)到 0,但这不应该是同一件事,因为这里不涉及函数调用。


可能是因为 x86 FPU 在寄存器中以 80 位精度工作,但在将值存储到内存时四舍五入到 64 位。 GDB 将在(解释的)计算的每一步中存储到内存中。

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

为什么 GDB 计算浮点运算的方式与 C++ 不同? 的相关文章

随机推荐

  • 基准测试 - 如何计算发送到 CPU 的指令数以查找消耗的 MIPS

    假设我有一个软件并想使用黑盒子 https en wikipedia org wiki Black box testing方法 我有一个 3 0GHz CPU 有 2 个插槽和 4 个核心 如您所知 为了找出每秒指令数 IPS 我们必须使用
  • 如何在 Eclipse 中打开现有的 Clojure 项目?

    我尝试按照通常的方式进行操作文件 gt 导入 gt 常规 gt 现有项目 对于java项目 但是eclipse看不到clojure项目并且无法打开它 你知道为什么吗 Install 逆时针 http doc ccw ide org docu
  • 如何在 Android 中恢复文件上传过程?

    我正在使用此代码在服务器上上传文件 但我想要这样的功能 如果在过程中由于网络丢失或任何其他中断而停止 那么它不应该从第二次开始上传 来自服务器的响应也是可定制的 在安卓上可以吗 我应该使用什么方法来做到这一点 请指导我 如果可能的话 请向我
  • 如何在 SunOs 的 df -k 命令中省略标题

    Input df k Output Filesystem kbytes used avail capacity Mounted on dev dsk c0t0d0s0 10332220 443748 9785150 5 devices 0
  • MVVM + 用户控件 + 依赖属性

    好吧 这与这个问题有些相关 WPF 从单个视图模型打印多个页面 https stackoverflow com questions 15162274 wpf printing multiple pages from a single vie
  • 检查 XML 中是否存在某个元素

    XML
  • asp.net mvc TextAreaFor 未验证为必填字段

    我有一个数据输入字段 我可以在其中收集笔记 每个注释都需要注释数据元素 这是我的模型 public interface INoteDataEntryViewModel IMobilePageDataContract int CourseId
  • 如何获取 svg:g 元素的宽度

    我目前正在与一个svgJavaScript 中的元素 我对此很陌生 我的问题是我有一个svg我有多个元素svg g元素 而在我的svg gelements 我有各种其他 svg 元素
  • 现实世界中的递归示例[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 什么是真实世界除了深度优先搜索 DFS 之外 递归方法是自然解决方案的问题吗 我不考虑河内塔 http en wikipedia or
  • 熊猫拆分列

    给定以下数据框 import pandas as pd import numpy as np df pd DataFrame A a b c d B Y gt abcd abcd efgh Y gt efgh df A B 0 a Y gt
  • 根据 C++ 标准的定义实现“is_similar”类型特征

    我正在尝试实施一个is similar基于标准给出的定义的类型特征 详细信息here http eel is c draft conv qual 2 两种类型T1 and T2如果它们具有 cv 分解 则它们是相似的 与相同的n使得对应的P
  • GAE 上的 Struts 2:无法在拦截器内设置会话值

    我正在编写一个 Struts 2 拦截器 在其中检查用户是否有效 如果无效 用户将被重定向到登录页面 但在此之前 我尝试检索用户访问此处的 URL 并将其放入会话变量中 以便在登录完成后我可以将他重定向回那里 但是当我尝试在会话中放入一个值
  • background-position-y 在 Firefox 中不起作用(通过 CSS)?

    在我的代码中background position y不起作用 在 Chrome 中可以 但在 Firefox 中不行 有人有什么解决办法吗 如果你的position x是0 除了写之外没有其他解决方案 background positio
  • Wiki 数据导入 virtuoso

    我想将维基数据加载到 virtuoso 中 经过几天的搜索 我找不到任何教程 或者至少找不到使用 virtuoso 来 sparql 查询 wikidata 的人 我不想白花钱买一台服务器来加载50G 的数据 例如 为什么是 virtuos
  • 使用polyfit来预测物体掉落的位置?

    我有一个物体以抛物线模式抛出的信息 从开始位置到结束位置 按照特定时间间隔总共拍摄了 30 张图像 现在我已经成功提取了所有 30 张图像中被抛出物体的 x y 坐标 我认为使用 polyfit 或者也许是 polyval 可以帮助我预测前
  • 如何使用 QSocketNotifier (linux) 监视串行端口?

    有人可以给我一个关于如何设置 QSocketNotifier 在发生事件时触发事件的示例吗 dev ttyS0 最好在 python pyqt4 中 下面是一个使用 QSocketNotifier 不断读取文件的示例 只需将 foo txt
  • SQL 2005中检查外键是否存在的方法

    有没有一种简单的方法来检查表中的列是否存在外键 我正在编写一个脚本 仅当外键不存在时才会添加外键 您可以使用这个脚本 IF EXISTS SELECT FROM sys foreign keys WHERE object id OBJECT
  • Google Javascript API 地理编码限制

    使用 Google Maps JavaScript API v3 进行客户端地理编码有哪些限制 我的研究 Google Maps PHP API 每天的地理编码请求限制为 2500 个 https developers google com
  • 如何将热量输出包含在 wix 文件中? (没有 Visual Studio 项目)

    我需要构建一个安装程序 并且出于多种原因 我想避免使用 WiX 项目模板 我非常高兴自己编写这些东西的脚本 并且已经有了一个适合它的自定义构建流程 我相信我很好地理解了 WiX 蜡烛 加热和照明工具的作用 我正在熟悉 wxs 文件格式 并且
  • 为什么 GDB 计算浮点运算的方式与 C++ 不同?

    我在尝试处理浮点算术问题时遇到了一些令人困惑的事情 首先 代码 我将问题的本质提炼到这个例子中 include