c - 为什么除法比乘以它的倒数更准确
问题描述
为什么 X/Y != X*(1/Y)?
为什么 X/Y 比 X*(1/Y) 更准确?
在我的矩阵逆的 C 编码中,我需要做
inv(inp) = [d -b; -c a]*(1/det(inp));
我通过两种方式做到了,
情况1:
temp = 1/det(inp);
inv(inp) = [d -b; -c a]*temp;
案例2:
inv(inp) = [d/det(inp) -b/det(inp); -c/det(inp) a/det(inp)];
与案例 2 中的零错误相比,为什么案例 1 有错误。
提前致谢。
解决方案
考虑1/41.f
。在实数数学中,1 除以 41 产生有理数 1/41。此数字不能以二进制浮点格式表示。在通常用于float
(IEEE-754 单精度)的格式中,我们可以得到的最接近 1/41 的格式是 13094412•2 -29。因此,如果det(inp)
是 41,并且您正在使用float
,则temp = 1/det(inp);
设置temp
为 13094412•2 -29。其中的 13094412 部分称为有效数字。
然后,如果我们计算41*temp
,实数数学中的结果将是 536870892•2 -29。该float
格式仅支持 24 位有效位,因此我将重新调整此结果以使有效位低于 2 24: 16777215.375•2 -5。正如我们所见,有效数字不是整数,因此它不适合float
表示。最接近的可表示值为 16777215•2 -5,即 0.999999940395355224609375。
因此,在这种情况下,41*(1/det(inp))
将给出 0.999999940395355224609375,而41/det(inp)
给出 1。
每当您执行给出浮点结果的操作时,实数数学结果将四舍五入为可表示的结果。这种舍入会引入一个小错误。在多个操作过程中,这些错误可能会以各种方式复合、取消或相互作用。通过计算行列式的倒数,您引入了直接除以行列式时不存在的错误。
(错误可以取消,因为有时一个操作中的舍入恰好与早期操作中的舍入方向相反。因此,有时即使各个操作都有错误,您也可以获得正确的结果。)
推荐阅读
- swift - Swift:不符合通用协议
- jquery - 无法将数据从 Form 发送到 SQL 数据库
- javascript - 当用户点击外部链接时触发对话框
- python - 发布和点击后如何抓取和解析页面?
- ibm-cloud - 不会使用 cf-cli 推送空文件夹(其中包含 .gitignore)
- javascript - 如何修复我在 5 秒后卡住的延迟循环?
- javascript - 在 JavaScript 中获取 API 以将表单数据保存到 JSON 或 TEXT 文件
- flutter - 如何导出和使用全局变量
- ip - colab 虚拟实例上笔记本的 IP 地址会随时间变化吗?
- react-native - 如何打开特定屏幕以反应原生方式显示通知的详细信息