首页 > 其他分享 >计算浮点数的差

计算浮点数的差

时间:2024-03-20 18:34:07浏览次数:23  
标签:std fabs epsilon 浮点数 计算 include 比较

浮点数不是完美精确的表示,尤其是在涉及到舍入误差和不同数值规模时。

一般实现:

fabs(a - b) < epsilon

这种通过比较差的绝对值来判断浮点数是否相等的方法,存在一些潜在的问题:

  1. 误差累积:在连续的浮点数运算中,误差可能会逐步累积。这会导致最后的结果偏离真实值,这样用差值来比较就可能得到错误的结果。
  2. 选择合适的epsilon不好确定:epsilon 的选择可能依赖于具体的应用和上下文,并不能确定一个通用的值。太大或者太小的 epsilon 都可能造成不准确的判断。例如,太小的值可能会使接近但并非相等的数被误判为相等;而太大的数则可能让实际相等的数被误判为不等。
  3. 容易受到溢出和欠流的影响:如果两个浮点数的差值太大或者太小,可能会导致溢出或者欠流,从而无法准确的表示出实际的差值。
  4. 在一些需要极高精度的场合这种方式可能无法满足需求。

以下是一些改进浮点数比较策略的方法:

相对误差比较

使用相对误差而非绝对误差来比较浮点数。这涉及到计算两个数的差相对于数值大小的比例,以确定它们是否足够接近。

bool areAlmostEqual(double a, double b, double epsilon) {
    // 在非常小的值附近使用绝对误差比较
    if (fabs(a - b) < epsilon) {
        return true;
    }
    // 使用相对误差比较
    return fabs(a - b) < epsilon * fmax(fabs(a), fabs(b));
}

使用 ULPs 比较(单位最后位置)

ULPs 比较是一种浮点数比较策略,它通过比较两个浮点数之间的表示差异来确定它们是否足够接近。这种方法可以处理不同数值规模的准确性问题,但实现起来较为复杂。

#include <algorithm>
#include <cmath>
#include <cstddef>
#include <iomanip>
#include <iostream>
#include <limits>
#include <type_traits>
 
template <class T>
std::enable_if_t<not std::numeric_limits<T>::is_integer, bool>
equal_within_ulps(T x, T y, std::size_t n)
{
    // Since `epsilon()` is the gap size (ULP, unit in the last place)
    // of floating-point numbers in interval [1, 2), we can scale it to
    // the gap size in interval [2^e, 2^{e+1}), where `e` is the exponent
    // of `x` and `y`.
 
    // If `x` and `y` have different gap sizes (which means they have
    // different exponents), we take the smaller one. Taking the bigger
    // one is also reasonable, I guess.
    const T m = std::min(std::fabs(x), std::fabs(y));
 
    // Subnormal numbers have fixed exponent, which is `min_exponent - 1`.
    const int exp = m < std::numeric_limits<T>::min()
                  ? std::numeric_limits<T>::min_exponent - 1
                  : std::ilogb(m);
 
    // We consider `x` and `y` equal if the difference between them is
    // within `n` ULPs.
    return std::fabs(x - y) <= n * std::ldexp(std::numeric_limits<T>::epsilon(), exp);
}
 
int main()
{
    double x = 0.3;
    double y = 0.1 + 0.2;
    std::cout << std::hexfloat;
    std::cout << "x = " << x << '\n';
    std::cout << "y = " << y << '\n';
    std::cout << (x == y ? "x == y" : "x != y") << '\n';
    for (std::size_t n = 0; n <= 10; ++n)
        if (equal_within_ulps(x, y, n))
        {
            std::cout << "x equals y within " << n << " ulps" << '\n';
            break;
        }
}

建议:

  1. 优先使用数学库函数:一些数学库提供了特制的函数用于浮点数的比较,例如 C++ 的 std::numeric_limits<double>::epsilon() 可以提供 double 类型可接受的最小差值。如果可行,优先使用这些函数,因为它们考虑了浮点数的底层细节。
  2. 避免差值比较:在设计算法和编写代码时,尽量避免将两个浮点数相减然后比较差值。这种情况下,尽可能设计算法以避免这种直接比较。
  3. 自定义比较运算符:在面向对象语言中(如 C++),你可以为使用到的浮点数类型定义自己的比较运算符,这些运算符内部使用更稳健的浮点数比较策略。
  4. 减少浮点数的使用:如转为int。

标签:std,fabs,epsilon,浮点数,计算,include,比较
From: https://www.cnblogs.com/txtp/p/18085837

相关文章

  • 【无标题】计算机图形学OpenGL基础
    一、OpenGL的主要功能模型绘制模型观察颜色模式光照应用图像效果增强位图和图像处理纹理映射实时动画交互技术二、OpenGL的绘制流程----------工作方式**一个完整的窗口系统的OpenGL图形处理系统的结构为:最底层为图形硬件,第二层为操作系统,第三层为窗口系统,第四层为OpenG......
  • 计算机选择题真题(大全)
    计算机系统(132)计算机完成一条指令所花费的时间称为一个(指令周期)顺序程序不具有(并发性)总线带宽是指总线的(数据传输率)一进程已获得除CPU以外的所有所需运行资源,经调度分配CPU给它后,该进程将进入(运行状态)CPU芯片内部连接各元件的总线是(内部总线)如果一个进程在运行时因某种原因......
  • 前端学习-vue学习007-计算属性+Class 与 Style 绑定
    官方教程链接Class与Style绑定Vue专门为class和style的v-bind用法提供了特殊的功能增强<span:class="{done:item.done}">{{item.text}}</span>如果item.done是true,以上代码实际为<span:class="done">{{item.text}}</span>如果item.done是false,......
  • 【附源码】java计算机毕设基于语言的在线电子书阅读系统(源码+开题)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着信息技术的迅猛发展,数字化阅读已成为人们获取知识和信息的重要途径。电子书以其便捷、环保、更新迅速等特点,逐渐替代了传统纸质书籍,成为大众阅读......
  • 【附源码】java计算机毕设基于网上书店的设计与实现(源码+开题)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着互联网技术的迅猛发展,电子商务已成为当今社会经济发展的重要引擎。网上书店作为电子商务的一种形式,以其便捷性、高效性和广泛覆盖性,正逐渐改变着......
  • 【附源码】java计算机毕设基于通识课程管理系统(源码+开题)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着信息技术的飞速发展,高等教育管理逐步迈向数字化、信息化。通识课程作为高等教育的重要组成部分,其管理效率和质量直接关系到学生的学习体验和学校......
  • 计算机网络的组成
    目录<计算机网络的组成>1.网络硬件1)主机Host2)终端Terminal3)通信控制处理机4)传输介质5)网络连接设备2.网络软件1)网络操作系统2)网络协议软件3)网络管理软件4)网络通信软件5)网络应用软件3通信子网和资源子网<计算机网络的组成>无论网络的复杂程度如何,从......
  • 计算机电子书 (二)- Java
    书名有夸克网盘超链接,点击后可免费快速下载。(内容完善中)~~~文章目录前言一、Java1.基础2.并发和多线程3.虚拟机4.设计模式二、JavaEE和Spring三、SpringBoot四、SpringCloud、微服务五、优化性能重构前言计算机电子书籍一、Java1.基础Java编程思想(第4版)......
  • 计算机电子书 (三)
    书名有夸克网盘超链接,点击后可免费快速下载。(内容完善中)~~~文章目录前言一、架构、分布式1.1分布式1.2网站1.3其它二、中间件2.1ZooKeeper2.2消息队列2.3搜索三、大数据、云计算前言计算机电子书籍一、架构、分布式1.1分布式分布式系统概念与设计大规模......
  • 学习大学计算机知识有用?“有用但不多”
    大学学习的计算机知识有用但真不多:1.知识更新迅速:计算机科学和技术是一个发展非常迅速的领域,新的技术和工具不断涌现。大学课程往往更侧重于基础理论和经典技术,而工作中可能需要使用最新的技术和工具,因此需要不断学习和更新知识。2.实践机会有限:大学课程通常注重理论知识的......