sqrt函数实现之卡马克方法

2023-11-11

sqrt函数的实现主要有三种方式:

  1. 二分法
  2. 牛顿法
  3. 卡马克方法

卡马克方法

这里主要介绍高效的卡马克方法。卡马克方法起源于《雷神之锤III竞技场》中使用的平方根倒数速算法,下列代码是平方根倒数速算法在《雷神之锤III竞技场》源代码中的应用实例。示例剥离了C语言预处理器的指令,但附上了原有的注释:

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

    x2 = number * 0.5F;
    y  = number;
    i  = * ( long * ) &y;// evil floating point bit level hacking
    i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
    y  = * ( float * ) &i;
    y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration 
//  y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed

    return y;
}

为计算平方根倒数的值,软件首先要先确定一个近似值,而后则使用某些数值方法不断计算修改近似值,直至达到可接受的精度。在1990年代初(也即该算法发明的大概时间),软件开发时通用的平方根算法多是从查找表中获取近似值,而这段代码取近似值耗时比之更短,达到精确度要求的速度也比通常使用的浮点除法计算法快四倍,虽然此算法会损失一些精度,但性能上的巨大优势已足以补偿损失的精度。由代码中对原数据的变量类型声明为float可看出,这一算法是针对IEEE 754标准格式的32位浮点数设计的,不过据Chris Lomont和后来的Charles McEniry的研究看,这一算法亦可套用于其他类型的浮点数上。
平方根倒数速算法在速度上的优势源自将浮点数转化为长整型以作整数看待,并用特定常数0x5f3759df与之相减。然而对于代码阅读者来说,他们却难以立即领悟出使用这一常数的目的,因此和其它在代码中出现的难以理解的常数一样,这一常数亦被称为“魔术数字”。如此将浮点数当作整数先位移后减法,所得的浮点数结果即是对输入数字的平方根倒数的粗略估计值,而后再进行一次牛顿迭代法,以使之更精确后,代码即执行完毕。由于算法所生成的用于输入牛顿法的首次近似值已经相当精确,此算法所得近似值的精度已可接受,而若使用与《雷神之锤III竞技场》同为1999年发布的Pentium III中的SSE指令rsqrtss计算,则计算平方根倒数的收敛速度更慢,精度也更低。

将浮点数转化为整数

img

要理解这段代码,首先需了解浮点数的存储格式。一个浮点数以32个二进制位表示一个有理数,而这32位由其意义分为三段:首先首位为符号位,如若是0则为正数,反之为负数;接下来的8位表示经过偏移处理(这是为了使之能表示-127-128)后的指数;最后23位表示的则是有效数字中除最高位以外的其余数字。将上述结构表示成公式即为 x=(1)Si(1+m)2(EB) x = ( − 1 ) S i · ( 1 + m ) · 2 ( E − B ) ,其中 m m 表示有效数字的尾数(此处 0m<1 0 m < 1 ,偏移量 B=127 B = 127 ,而指数的值 EB E − B 决定了有效数字代表的是小数还是整数。以上图为例,将描述带入有 m=1×22=0.250 m = 1 × 2 − 2 = 0.250 ,且 EB=124127=3 E − B = 124 − 127 = − 3 ,则可得其表示的浮点数为 x=(1+0.250)23=0.15625 x = ( 1 + 0.250 ) · 2 − 3 = 0.15625

如上所述,一个有符号正整数在二进制补码系统中的表示中首位为0,而后面的各位则用于表示其数值。将浮点数取别名存储为整数时,该整数的数值即为 I=E×223+M I = E × 2 23 + M ,其中E表示指数,M表示有效数字;若以上图为例,图中样例若作为浮点数看待有 E=124 E = 124 M=1221 M = 1 · 2 21 ,则易知其转化而得的整数型号数值为 I=124×223+221 I = 124 × 2 23 + 2 21 。由于平方根倒数函数仅能处理正数,因此浮点数的符号位(即如上的Si)必为0,而这就保证了转换所得的有符号整数也必为正数。以上转换就为后面的计算带来了可行性,之后的第一步操作(逻辑右移一位)即是使该数的长整形式被2所除

“魔术数字”

对猜测平方根倒数速算法的最初构想来说,计算首次近似值所使用的常数0x5f3759df也是重要的线索。为确定程序员最初选此常数以近似求取平方根倒数的方法,Charles McEniry首先检验了在代码中选择任意常数R所求取出的首次近似值的精度。回想上一节关于整数和浮点数表示的比较:对于同样的32位二进制数字,若为浮点数表示时实际数值为 x=(1+mx)2ex x = ( 1 + m x ) 2 e x ,而若为整数表示时实际数值则为 Ix=ExL+Mx I x = E x L + M x ,其中 L=2

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

sqrt函数实现之卡马克方法 的相关文章

  • 软件设计师考试内容复习(二)

    一 层次化存储结构 二 Cache Cache的功能 提高CPU数据输入输出的速率 突破CPU与存储系统间数据传输带宽限制 在计算机存储系统体系中 Cache是访问速度最快的层次 使用Cache改善系统性能的依据是程序的局部性原理 如果以
  • 【计算机网络】OSI参考模型与TCP/IP分层模型对比(体系结构对比)

    笔记整理 协议 简单来说 协议就是计算机与计算机之间通过网络实现通信时事先达成的一种 约定 这种约定使得那些由不同厂商的设备 不同的操作系统组成的计算机之间 只要遵循相同的协议就能够实现通信 就好比两个人使用不同国家的语言就行对话 是无法相
  • 计算机网络笔记(一)

    什么是计算机网络 什么是计算机网络 计算机网络就是互连 互联互通 的 自治 无主从关系 的计算机集合 那么 距离远 数据大如何保证互连 通过交换网络互连主机 什么 是 Internet 组成 计算机设备 通信链路 分组交换 数据包转发分组
  • win10如何校验文件哈希值

    转自 https jingyan baidu com article 67662997a9b06654d51b84a1 html 文件的哈希值可以用软件计算 算法一样 无须多讲 本文讲述如何用win10自带命令计算 右击开始 点击windo
  • 数据结构-线性表(链表)(c++版)

    目录 1 单链表的基本概念与特点 2 单链表的特点 3 单链表的结构定义及其方法的实现 3 1 单链表结构的定义 3 2 方法的基本实现 3 3 单链表的插入删除操作讲解 3 4 单链表的删除算法 3 5 单链表的顺序访问与尾递归 3 6
  • 记一次Tomcat日志分析:一个或多个listeners启动失败,更多详细信息查看对应的容器日志文件

    1 问题 我将一个应用 MicroStrategy 11 3 0000 13515 部署到Tomcat 然后 我点击start后报错 FAIL Application at context path MicroStrategy 11 3 0
  • 【深入理解计算机系统-学习笔记】第一章 计算机系统漫游

    第一章 计算机系统漫游 简介 我们通过跟踪hello程序的生命周期来开始对系统的学习 从它被程序员创建开始 到在系统上运行 输出简单的消息 然后终止 我们将沿着这个程序的生命周期 简单得介绍一些逐步出现的关键概念 专业数据和组成部分 hel
  • 大学计算机基础 - 第十一章习题

    1 选择题 1 多媒体计算机中的媒体信息是指 D 文字 音频 音频 图形 动画 视频 视频 音频 A B c D 全部 2 多媒体技术的主要特性有 C 多样性 集成性 交互性 实时性 A 仅 B c D 全部 多媒体技术具有以下基本特征 1
  • MySQL8 EXPLAIN 命令输出的都是什么东西?这篇超详细!

    引子 小扎刚毕业不久 在一家互联网公司工作 由于是新人 做的也都是简单的CRUD 刚来的时候还有点不适应 做了几个月之后 就变成了熟练工了 左复制 右粘贴 然后改改就是自己的代码了 生活真美好 有一天 领导说他做的有个列表页面速度很慢 半天
  • 计算机基础操作

    1 计算机软件 计算机软件可以使计算机按照事先预定好的顺序完成特定的功能 计算机软件按照其功能划分为系统软件与应用软件 系统软件 DOC Disk Operating System Windows Linux Unix Mac Androi
  • 如何最高效实现手机~电脑端文件传输?

    平常使用电脑办公的时候 经常会有把手机上的文件传到电脑或把电脑上的文件分发给局域网 内网 的各个伙伴的情况 通常我们会选择使用QQ或微信的文件传输功能来实现 但是当文件比较大 比较多时 就无法发送了 再者每次通过文件助手来发送文件时 其本质
  • 软件设计命名规范

    1 命名约定 Pascal和Camel命名约定 编程的命名方式主要有Pascal和Camel两种 Pascal 每个单词的首字母大写 例如ProductType Camel 首个单词的首字母小写 其余单词的首字母大写 例如productTy
  • 字节和比特简单介绍

    字节 byte 字节为Byte 多数用B表示 字节为计算机中数据处理的基本单位 比特 bit 又称位 表示二进制位 为计算内部数据存储的最小单位 关系 1Byte 8bit 其他单位 1B Byte 字节 8bit 1KB Kilobyte
  • arm的多级流水线技术和和存储管理单元mmu

    流水线概念 流水线的概念与原理 处理器按照一系列步骤来执行每一条指令 典型的步骤如下 1 从存储器读取指令 fetch 2 译码以鉴别它属于哪一条指令 decode 3 从指令中提取指令的操作数 这些操作数往往存在于寄存器reg中 4 将操
  • ip地址查询到网络地址和广播地址

    借鉴 维基百科 分类网络 百度百科 IP地址 维基百科 IP地址 名词解释 IP地址 互联网协议地址 英语 Internet Protocol Address 又译为网际协议地址 缩写为IP地址 英语 IP Address 是分配给网络上使
  • 如何使用Visual Studio Code运行C/C++程序

    与Visual Studio 2008 2010 集成开发工具不同 Visual Studio Code只是一个代码编辑器 在Windows环境下 需下载安装 C C 编译器 配置环境等 VS Code才可以编译代码和运行程序 1 下载安装
  • 进程的描述与组织

    1 1 1进程的资源 进程需要一定资源才能运行 最重要的资源是内存地址空间 此外还可能需要使用文件 设备等 这些资源均由内核负责管理和分配 分配给进程的资源登记在进程的PCB中 1 进程的地址空间 进程的一个重要构成成分是进程映像 即进程所
  • 【数据结构】堆、栈的区别

    heap 是堆 stack 是栈 在编程语言中 内存分配方式主要包括 栈 堆 静态存储分配 栈的内存是由操作系统自动分配 释放的 存放函数的参数值 局部变量等 堆的内存是由程序员手动申请和释放的 对应C语言中的malloc函数和C 中的ne
  • 【编译原理】 CS143 斯坦福大学公开课 第一周:简介

    youtube 1 1 Introduction to Compilers and interpreters 1 1 Introduction to Compilers and interpreters 编译器解释器介绍 两种主要的实现编程
  • 计算机中的二进制表示-4和5

    十进制 二进制 5 00000000 00000000 00000000 00000101 4 11111111 11111111 11111111 11111100 负数的二进制如何得出 相信正数的二进制表示大家都懂 但是这个 4怎么来的

随机推荐

  • 利用eclipse比较两个文件的代码差异或者一个文件不同版本之间的异同

    1 比较两个文件之间的代码差异 选中两个文件 右键选择Compare With 再选择Each Other即可 2 比较一个文件不同版本之间的差异 选中文件 右键选择team 选择显示资源历史记录 然后从历史记录中选择需要比较的版本 两个文
  • moment.js的使用方法和日期格式化介绍

    文章目录 1 node js 2 使用方法 日期格式化介绍 fromNow 相对时间 startOf 时间开头 endOf 时间末尾 subtract 时间减 add 时间加 获取星期几 moment 被设计为在浏览器和 Node js 中
  • Java多线程程序设计初步

    Java多线程程序设计初步 在Java语言产生前 传统的程序设计语言的程序同一时刻只能单任务操作 效率非常低 例如程序往往在接收数据输入时发生阻塞 只有等到程序获得数据后才能继续运行 随着Internet的迅猛发展 这种状况越来越不能让人们
  • 1.pytorch lightning之验证与测试

    训练 训练部分已在 入门篇 介绍 验证集和测试集中评估模型 通常将数据集分为三部分 train val test val集在训练时评估模型的泛化性 选择其中表现最好的checkpoint test集只在模型训练完成后使用 用于评估模型的真实
  • 封装微信小程序隐私信息授权

    隐私 代码 html modal 组件再后面封装有提供
  • 深入理解Java国际化

    假设我们正在开发一个支持多国语言的Web应用程序 要求系统能够根据客户端的系统的语言类型返回对应的界面 英文的操作系统返回英文界面 而中文的操作系统则返回中文界面 这便是典型的i18n国际化问题 对于有国际化要求的应用系统 我们不能简单地采
  • [深度学习] 名词解释--正则化

    正则化 花书的定义 凡是可以减少泛化误差 过拟合 而不是减少训练误差的方法 都叫正则化方法 目的 拟合训练数据 防止模型过拟合 通常使用L2正则化 用各种方法规范模型参数的方法 什么是神经网络的过拟合 在最小化损失函数的前提下 最优的一组w
  • proteus中继电器怎么找_(踩坑记录)——数电仿真proteus/ewb

    我不管 从今天开始我要隐姓埋名的在知乎记录各种学习和生活上遇到的坎了 因为实在不知道记录在哪里方便查找 为什么要记录呢 还不是我脑子不好 彻底卸载proteus 正常卸载 删除注册表 win R输入以下 数电仿真实验 1 一 逻辑门 74L
  • 冷月手撕408之操作系统(5)-进程概述

    操作系统的进程概述主要是介绍了进程的概念 进程的组成 进程实体 进程的特征 进程的五状态模型 进程控制 其中重点掌握PCB 五状态模型及其状态转换 主要的重点冷月做出了标识 知识点如下图 pdf版或xmind源文件请关注公众号 学长冷月 回
  • 【算法】排序(sort排序函数和冒泡、选择、插入、快速排序)

    记录目前学到的4种排序 sort函数排序 冒泡排序 选择排序 插入排序 sort函数排序 1 对数组进行排序 要加函数头 include
  • ChatGPT:我的生活工作“解忧公主”

    1 概述 在这个充满活力与挑战的时代 我们的生活和工作总是充满了各种问题 幸运的是 有了 ChatGPT 这位 解忧公主 我们能轻松应对这些问题 高效地度过每一天 本文将分享 ChatGPT 如何成为我们生活工作中的万能钥匙 我们将从以下几
  • python3的面向对象

    python的面向对象也很强大 支持多继承 php和java都是单继承 但都可以实现其他接口 self 类似java的this test py usr bin python3 基类 class Base 父类属性 name age 60 定
  • Windows下fopen,fclose

    Fopen fclose 在头文件 include
  • KiCad使用笔记(05)-PCB绘制

    文章目录 绘图过程 导入网表 绘制PCB边框 摆放元件 添加导线 交互式布线 添加铺铜 放置过孔 检测PCB 整理丝印 生成钻孔文件 生成光绘文件 相关视频教程 绘图过程 导入网表 绘制PCB边框 PCB边框放置在Edge Cuts层 可以
  • Java课题笔记~ SpringBoot简介

    1 入门案例 问题导入 SpringMVC的HelloWord程序大家还记得吗 SpringBoot是由Pivotal团队提供的全新框架 其设计目的是用来简化Spring应用的初始搭建以及开发过程 原生开发SpringMVC程序过程 1 1
  • useEffect实现数据请求刷新的几种方法

    请求数据入参变化的情况下重新请求数据的情景下useEffect的几种写法 1 函数在useEffect里面 const query useEffect gt function fetchData return https hn algoli
  • Redis-大key解决策略

    大key的定义 首先大key不是key很大而是key对应的value值很大 一般而言如果String类型值大于10KB Hash Set Zset List类型的元素的个数大于5000个都可以称之为大key 大key的危害 客户端超时等待
  • 通过示例学习 PyTorch

    通过示例学习 PyTorch 本教程通过独立的示例介绍 PyTorch 的基本概念 PyTorch 的核心是提供两个主要功能 n 维张量 类似于 numpy 但可以在 GPU 上运行 自动区分以构建和训练神经网络 我们将使用完全连接的 Re
  • 自动化测试的一些面试题分享

    一 Web自动化测试 1 Selenium中hidden或者是display none的元素是否可以定位到 不能 可以写JavaScript将标签中的hidden先改为0 再定位元素 2 Selenium中如何保证操作元素的成功率 也就是说
  • sqrt函数实现之卡马克方法

    sqrt函数的实现主要有三种方式 二分法 牛顿法 卡马克方法 卡马克方法 这里主要介绍高效的卡马克方法 卡马克方法起源于 雷神之锤III竞技场 中使用的平方根倒数速算法 下列代码是平方根倒数速算法在 雷神之锤III竞技场 源代码中的应用实例