C语言求平方和倒数

news2024/9/21 12:36:48

文章目录

    • 1. 代码实现
      • float类型数据
      • double类型数据
      • 使用 double 类型的调整
    • 2. 魔数与位级别操作
      • 浮点数表示
      • 位级别魔数操作
    • 3. 牛顿迭代
    • 4. 复杂代码具体解释
      • 具体解释:
      • 目的:
      • 举例:
    • 5.感谢

平方和倒数 广泛用于计算机图形学中,尤其是在处理大规模3D渲染时。这种方法的核心思想是利用了位级别的操作和牛顿迭代法,以非常高效的方式计算平方根的倒数。

平方根倒数(Reciprocal Square Root)计算的问题是,对于一个给定的数 n,我们希望快速找到 1/√n。在图形学和物理模拟中,这种计算非常常见,通常用于归一化向量。

传统的平方根计算通常使用浮点运算,较为耗时。为了提高效率,特别是在早期硬件性能有限的情况下,出现了一种基于“魔数”(magic number)的快速算法。


1. 代码实现

float类型数据

float Q_rsqrt(float n)
{
    long i;
    float x2, y;
    const float threehalfs = 1.5F;

    x2 = n * 0.5F;
    y = n;
    i = *(long *)&y;
    i = 0x5f3759df - (i >> 1);
    y = *(float *)&i;

    // First iteration
    y = y * (threehalfs - (x2 * y * y));
    // Second iteration for higher precision
    y = y * (threehalfs - (x2 * y * y));
    // Third iteration for higher precision
    y = y * (threehalfs - (x2 * y * y));
    // Fourth iteration for higher precision
    y = y * (threehalfs - (x2 * y * y));

    return y;
}

double类型数据

double Q_rsqrt(double n)
{
    long long i;
    double x2, y;
    const double threehalfs = 1.5;

    x2 = n * 0.5;
    y = n;
    i = *(long long *)&y;
    i = 0x5fe6eb50c7b537a9 - (i >> 1); // 使用64位常量
    y = *(double *)&i;

    // First iteration
    y = y * (threehalfs - (x2 * y * y));
    // Second iteration for higher precision
    y = y * (threehalfs - (x2 * y * y));
    // Third iteration for higher precision
    y = y * (threehalfs - (x2 * y * y));
    // Fourth iteration for higher precision
    y = y * (threehalfs - (x2 * y * y));

    return y;
}

使用 double 类型的调整

在处理 double 类型时,需要进行一些调整:

  • long 类型需要扩展为 long long 以适应 64 位浮点数的表示。
  • 魔数 0x5f3759df 替换为适用于 64 位的 0x5fe6eb50c7b537a9

2. 魔数与位级别操作

这个方法的核心是通过使用魔数对浮点数进行位级别的操作,得到平方根倒数的一个初始近似值。

浮点数表示

在现代计算机中,浮点数通常采用 IEEE 754 标准表示,包括符号位、指数部分和尾数部分。对于 32 位浮点数来说,结构如下:

  • 1 位符号位
  • 8 位指数部分
  • 23 位尾数部分

位级别魔数操作

Q_rsqrt 方法的精妙之处在于,它将浮点数视作一个整数,通过操作位来得到平方根倒数的近似值。核心操作如下:

i = 0x5f3759df - (i >> 1);

在这个公式中,i 是浮点数 y 在内存中的位表示,0x5f3759df 是一个特定的常量,这个常量通过经验或实验计算得出,能够将位级别的操作映射到一个相对合理的平方根倒数的近似值。对于 double 类型,需要将这个常量替换为 64 位的版本,即 0x5fe6eb50c7b537a9

这个操作的本质是近似计算了数值的对数,再通过魔数进行校正,使得结果在位操作的基础上接近实际的平方根倒数值。

3. 牛顿迭代

初始近似值得到后,使用牛顿迭代法进一步提高精度。牛顿迭代法是一种经典的数值方法,用于求解方程的根。对于平方根倒数问题,目标是找到 y,使得 y = 1/√n

牛顿迭代的公式如下:

y = y * (threehalfs - (x2 * y * y));

其中:

  • x2 = n * 0.5,是数值的一半,用于简化计算。
  • threehalfs = 1.5,是一个常量,用于调整收敛速度和稳定性。

这个公式利用当前的 y 值,结合原数 n,逐步逼近实际的 1/√n。每次迭代后,y 的值会变得更接近真实的平方根倒数值。

为了提高精度,通常会进行多次迭代。在最常见的实现中,进行一次或两次迭代已经可以满足大部分应用场景中的精度要求。

4. 复杂代码具体解释

代码 i = *(long *)&y; y = *(float *)&i; 是一种类型惩断(type punning)的操作方式,用于在不改变底层数据的情况下,以另一种类型访问相同的内存位置。以i = *(long *)&y;为例:

具体解释:

  • y 是一个 float 类型的变量。
  • &y 获取的是变量 y 的内存地址,这个地址是指向 float 类型数据的指针。
  • (long *)&y 将这个 float 类型的指针强制转换为 long 类型的指针。注意,这个操作并不改变 y 的实际数据,只是告诉编译器,“虽然 &y 原本是 float* 类型,但我要以 long* 类型来看待它。”
  • *(long *)&y 是取出这个 long* 指针所指向的数据。这意味着它会将 y 所在内存位置的位模式当作一个 long 类型的整数来读取。

目的:

在这种操作中,i 将会持有 y 变量的位表示形式,但被解释为一个 long 整数。这种操作允许我们以整数的形式直接操纵浮点数的底层位数据。在 Q_rsqrt 算法中,目的是利用这个位模式来快速估算平方根的倒数。

举例:

假设 y 是一个 float 类型的变量,假定其在内存中的二进制表示为 0x40490FDB(假设是浮点数 3.14159 的表示)。将它以 long 类型解读后,i 就会得到一个与 0x40490FDB 位模式相同的整数值。

这种方法的核心在于能够绕过浮点数的常规处理路径,直接对其位级别的数据进行操作,从而实现快速近似计算。这在一些高性能要求的算法中非常常见,特别是在图形处理、信号处理等领域。

5.感谢

代码出自小黑盒贴吧的一位老哥的分享,学习之后觉得着实精妙,针对代码中的重点部分进行了详细解释并分享给大家,再次感谢老哥分享!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1995373.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt实现类似淘宝商品展示看板功能简版

前一篇文章的简化版本只有浏览功能,前一篇文章链接如下: Qt实现类似淘宝商品看板的界面,带有循环翻页以及点击某页跳转的功能 效果如下: 代码留给有需要的人。 #ifndef ModelDashboardGroup_h__ #define ModelDashboardGroup_…

DC-DC PCB 布线参考

在DC-DC芯片的应用设计中,PCB布板是否合理对于芯片能否表现出其最优性能有着至关重要的影响。不合理的PCB布板会造成芯片性能变差如线性度下降(包括输入线性度以及输出线性度)、带载能力下降、工作不稳定、EMI辐射增加、输出噪声增加等&#…

容量 动效 仪表盘 Canvas 2D API

容量动效 <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Canvas 内部圆形波浪</title><…

【区块链+乡村振兴】基于区块链的农权抵押贷款平台 | FISCO BCOS应用案例

当前两权抵押贷款业务逐渐活跃&#xff0c;但因参与两权抵押的相关方独立运营各自的管理系统&#xff0c;办理农权抵押贷款业务时&#xff0c; 存在多方信息不对称、业务办理过程繁琐、低效等问题&#xff0c;且不利于相关部门对农权抵押情况进行监督管理。具体表现在&#xff…

《数据资产管理核心技术与应用》相关分享章节

【图书推荐】《数据资产管理核心技术与应用》-CSDN博客 图书《数据资产管理核心技术与应用》介绍-CSDN博客 本文用于快速了解数据资产管理的概念及其技术范围。 数据资产通常是指那些可以通过分析来揭示价值、支持企业决策制定、优化企业流程、预测行业的未来趋势或产生更大…

dhcp+checkkickstar的实验理解

文章目录 实验介绍使用的服务介绍PXE服务dhcp服务Kickstart 服务tftp服务 第一部分&#xff08;基础部分&#xff09;代码展示注意点第一点![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/13c0f4aabb664655a4dd285dd8e5527a.png)第二点 结果展示 第二部分&#xff08…

元岳食堂采购供应链系统-智慧食堂数据化解决方案

随着社会的发展和科技的进步&#xff0c;在数字化浪潮的推动下&#xff0c;智慧食堂供应链系统逐渐成为食堂管理的重要工具。在此背景下&#xff0c;元岳食堂采购供应链系统应运而生&#xff0c;该系统通过其独特的数字化和自动化功能&#xff0c;能够对食堂的采购、储存、配送…

重庆市合川区第二届网络安全“钓鱼城“杯部分题解

MISC 下载文件后&#xff0c;进行分析 往下划看见smb 最开始以为是通过smb协议下载的文件 找半天没发现&#xff0c;往前翻了翻&#xff0c;看见了flag 存储为原始数据 通过上述分析发现开头是pk&#xff0c;保存为zip压缩包 发现需要密码 感觉是伪加密 使用工具一把梭 再…

免费的GA/T1400视图库平台Easy1400软件又迭代出新版本了!

自从年初发布了这款免费的GA1400视图库平台&#xff08;https://blog.csdn.net/xiejiashu/article/details/135050381&#xff09;&#xff0c;本来就是想做一做能给大家差不多能用就行了&#xff0c;没成想总是忍不住要改一改、优化优化&#xff0c;于是又经过了几个月的优化&…

合宙Air201定位模组,千万不要忘记设置这个......

最近一个杭州的客户&#xff0c;使用合宙的 Air201——4G资产定位模组&#xff0c;做室内wifi定位&#xff0c;发现在同一园区不同楼栋内定位结果相同&#xff0c;找到我们希望做问题排查。 排查过程记录在这里了&#xff0c;如果你也有类似问题&#xff0c;希望可以帮助到你~ …

Pinterest:从 Druid 到 StarRocks,实现 6 倍成本效益比提升

导读&#xff1a; 开源无国界&#xff0c;StarRocks 自开源以来&#xff0c;近3年的时间里已在全球数据技术领域崭露头角。我们欣喜地发现&#xff0c;越来越多的海外用户正在使用并积极推广着 StarRocks。为了促进知识共享&#xff0c;StarRocks中文社区将精选优秀文章与大家共…

华为手机平板开启下方提示条(横条)

打开设置&#xff0c;系统与更新&#xff0c;系统导航方式&#xff0c;手势导航&#xff0c;更多设置&#xff0c;显示提示条。 该功能部分机型不支持&#xff0c;我的MatePad SE支持&#xff08;别买&#xff0c;割韭菜&#xff09;

有自增变量作为循环条件的循环边界的理解

while (i < 100) 先判断后增加 当次i值用于判断&#xff0c;范围1~99&#xff0c; 递增后的i值为当次循环值&#xff0c;即循环内的i值&#xff0c;范围2~100 当 i 9 时&#xff0c;小于 100&#xff0c;进入循环体。在进入循环体之前&#xff0c;i 递增为 10。10满足i…

面试笔记--(正在整理版)

面试常见: Jvm&#xff0c;高并发&#xff0c;多线程&#xff0c;数据库&#xff0c;redis&#xff0c;框架 多线程 1.线程和进程是什么?如何保证线程安全性? 进程线程&#xff08;一&#xff09;——基础知识&#xff0c;什么是进程&#xff1f;什么是线程&#xff1f;_…

手机卡换了上网的ip会改变吗

在数字化时代&#xff0c;互联网已成为我们日常生活不可或缺的一部分。无论是工作、学习还是娱乐&#xff0c;我们都离不开网络的支持。而每当涉及到网络连接&#xff0c;IP地址这一概念便显得尤为重要。IP地址不仅是设备在网络中的唯一标识&#xff0c;还关系到我们的网络体验…

Selenium + Python 自动化测试06(frame操作方法)

上一篇我们讲述了特殊元素的操作方法&#xff0c;本篇接着讲一些可能遇到的其它操作方法。 如frame操作。 Frame 标签有Frameset、Frame、Iframe 3种&#xff0c;Frameset可以直接照常进行元素定位。Frame、Iframe需要驱动切换到对应的frame才可以定位到。否则 &#xff0c;会…

Python基础-->数据类型/变量/运算符

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 一.变量 变量是一个保存数据的容器&#xff0c;变量通常分为变量和常量&#xff0c;常量中存储的是固定数据&#xff0c;而变量中存储的数据是可变的。 # 定义常量 PI 3.14159# 定义变量 rad…

service调mapper

为什么要用连接池 springboot项目连接池是什么 数据库如何配置 数据库如何开发 步骤&#xff1a; 1、先得到这个类hikariDataSource对象 HikariDataSource hikariDataSource new HikariDataSource();2、用这个类调set方法获取url,name,pwd等 //连接数据库的基本信息 HikariD…

动态规划数学问题前缀思想

前言&#xff1a;看到这个题目&#xff0c;感觉有点像动态规划&#xff0c;因为数据量有点大&#xff0c;不可能去枚举所有的情况 我们定义 dp[ i ] 为以 a[ i ] 结尾的方案数&#xff0c;用变量qian 记录 i 之前的所有枚举的情况 如果 a[ i ] 是奇数&#xff0c;那么 qian q…

浅谈面向数据报的协议-UDP协议

1.什么是网络协议 协议用通俗的话来说就是约定&#xff0c;因为计算机之间的传输媒介是光信号和电信号. 通过 "频率" 和 "强弱" 来表示 0 和 1 这样的信息. 要想传递各种不同的信息, 就需要约定好双方的数据格式. 计算机生产厂商有很多; 计算机操作系统, …