当前位置: 首页 > news >正文

为什么浮点数会搞出Infinity和NAN两种类型?浮点数的底层原理?IEEE 754标准揭秘?

目录

什么是NAN?

不同编程语言的NaN

为什么浮点数会搞出Infinity和NAN两种类型?

浮点数

小数点位置浮动的原因

浮点数和整数

浮点数指令

精确性

浮点数的类型

为什么叫浮点数?

小数点位置浮动的原因

IEEE 754起源于intel公司

IEEE 754标准

编程语言的浮点数都使用IEEE754吗?

浮点数指令

浮点数的精确性差?

浮点数操作丢失精度


什么是NAN?

NAN全称是Not a Number,常在浮点数运算中使用,首次引入NaN的是1985年的IEEE 754浮点数标准。如除以零、求负数的平方根等错误的操作,会返回NAN. 例如可以求一个负数的平方根,结果用isnan函数(来自math.h)返回真。

不同编程语言的NaN

  • JS全局函数isNaN和ES6引入的Number.isNaN函数存在差异,后者更符合字面理解。
    Number.isNaN(undefined)返回false,而全局isNaN(undefined)返回true.

为什么浮点数会搞出Infinity和NAN两种类型?

本质上,Infinity和NAN内部存储依然是一个浮点数,只是需要和正常的浮点数区分开。IEEE754标准规定浮点数有指数E和尾数M部分,标准规定当E等于255(E的最大值),可代表Infinity无穷和NAN非数两种。

  • E == 255,M == 0:Infinity
  • E == 255,M != 0: NAN

这意味着,其它任何有效的浮点数指数E都不会是255.

浮点数

浮点数相比定点数或者整数,为了处理小数点引入了指数,导致小数点的位置根据不同浮点数而不同,故名为Floating Point Number. 一般而言,IEEE754标准被大部分编程语言的浮点数使用,它节省了浮点数的保存空间。如不然,浮点数可能按每一位ASCII码保存,包括整数部分、小数点和小数部分,占用空间不可控制。

小数点位置浮动的原因

浮点数整数部分长度不一,为了统一整数部分和指数部分,把所有整数都转换成0.xx格式,造成小数点位置不一。

浮点数和整数

  • 浮点数的位级存储和整数完全不同,整数1和浮点数1.0存储也截然不同。通过调试器查看int变量和float变量的内存存储,或者写一段dump字节代码比较其区别,还有一种方式,C/C++ %a格式串可用十六进制形式表达浮点数(其他编程语言可能不适用)。
  • 不同浮点数位级存储也不相同,float和double是不同的。
  • 浮点数和整数运算,整数会默认先转换成浮点数。
    f = f + i;
    cvtsi2ss xmm0,dword ptr [i]
    addss xmm0,dword ptr [f]
    movss dword ptr [f],xmm0

浮点数指令

早期计算机根本没有浮点数处理ALU,浮点数靠软件整数去模拟,性能极低。后来,加入了浮点数FPU,浮点数处理速度极大提升,比如xmm寄存器。

  • double f = 2.25; // IEEE 754内存存储
  • 00501056 movsd xmm0,mmword ptr [__real@4002000000000000 (0502108h)]

精确性

浮点数的表达方式利用整数位和小数位计算的2n数值(n可正可负)计算,必然出现不准确。1.5可精确表示,0.3却无法精确表示。有的书籍上提到,浮点数不要用==或!=判断,其实是考虑有不精确表达的可能。在商业银行金融领域,这是不能容忍的。市面上,只要是用IEEE 754标准表达的浮点数,运算一定是不精确的。

  • COBOL编程语言是上古时期可以处理小数精确度很好的一门语言,因为它真的用模拟的形式保存小数点和小数位,而非IEEE 754这种压缩版。
  • C#引入了decimal类型处理小数点更精确。如下两种不同类型变量输出的结果第一个会更精确。
    decimal d = 3.14159265124m;
    float f = 3.14159265123f;

浮点数的类型

尽管4字节的浮点数可表达相当大的数值,但对于人类而言,总不够用。一般而言,浮点数有3种类型,单精度的float和双精度的double以及更长的long double, 可参考:数据类型大小

  • C语言为了区分float和double, 输入时用%f代表float, %lf代表double, 但对于输出%f和%lf作用相同。
  • C语言中float类型是默认转换成double去处理,如下图所示。
  • C99引入了long double (%Lf), 注意并不意味long double一定比double要长,根据编译器选择。

为什么叫浮点数?

浮点数相比定点数或者整数,为了处理小数点引入了指数,导致小数点的位置根据不同浮点数而不同,故名为Floating Point Number. 一般而言,IEEE754标准被大部分编程语言的浮点数使用,它节省了浮点数的保存空间。如不然,浮点数可能按每一位ASCII码保存,包括整数部分、小数点和小数部分,占用空间不可控制。

小数点位置浮动的原因

浮点数整数部分长度不一,为了统一整数部分和指数部分,把所有整数都转换成0.xx格式,造成小数点位置不一。

浮点数和整数有什么不同?

IEEE 754起源于intel公司

1980年,intel公司发布8087浮点数协处理器,它对浮点数的设计还算不错,被IEEE采纳为标准。它设计了3块,符号位、指数域和分数值。本质上是在较小的空间,如4字节或8字节,分成不同位域,存储更多数值的讯息,避免用一个字节表示十进制浮点数一位,造成空间浪费。

IEEE 754标准

IEEE 754是IEEE二进制浮点数算术标准(IEEE Standard for Floating-Point Arithmetic)的简称,于1985年首次发布,并在后续的1987年、2008年和2019年进行了修订。这是由国际电气和电子工程师协会(Institute of Electrical and Electronics Engineers,IEEE)制定的一种浮点数运算标准,也是20世纪80年代以来最广泛使用的浮点数运算标准,被许多CPU与浮点运算器所采用。大部分编程语言都采用IEEE 754标准作为浮点数标准,C语言诞生比它还早,后面也是采用此标准。

IEEE 754起源于intel公司

编程语言的浮点数都使用IEEE754吗?

对于主流的一些编程语言,例如C、Objective-C、C++、Swift、C#、Java和JavaScript都按照IEEE754标准实作浮点数。

浮点数指令

早期计算机根本没有浮点数处理ALU,浮点数靠软件整数去模拟,性能极低。后来,加入了浮点数FPU,浮点数处理速度极大提升,比如xmm寄存器。最早有FPU功能是intel的8087处理器。

  • double f = 2.25; // IEEE 754内存存储
  • 00501056 movsd xmm0,mmword ptr [__real@4002000000000000 (0502108h)]

浮点数的精确性差?

浮点数的表达方式利用整数位和小数位计算的2n数值(n可正可负)计算,必然出现不准确。1.5可精确表示,0.3却无法精确表示。有的书籍上提到,浮点数不要用==或!=判断,其实是考虑有不精确表达的可能。在商业银行金融领域,这是不能容忍的。

  • COBOL编程语言是上古时期可以处理小数精确度很好的一门语言,因为它真的用模拟的形式保存小数点和小数位,而非IEEE 754这种压缩版。
  • C#引入了decimal类型处理小数点更精确。如下两种不同类型变量输出的结果第一个会更精确。
    decimal d = 3.14159265124m;
    float f = 3.14159265123f;

浮点数操作丢失精度

  • C# 提供了round-trip格式符R或者r可以确保浮点数在运算过程中没有丢失精度。
    例如 string s = string.Format("{0:R}", float_val), 字符串s在后面被重新解析成浮点数不会改变。

浮点数指令 不同的浮点数类型 计算机存储单元bit


若文章对您有帮助,欢迎关注 程序员小迷 。助您在编程路上越走越好!

微风不燥,阳光正好,你就像风一样经过这里,愿你停留的片刻温暖舒心。

我是 程序员小迷 (致力于C、C++、C#、Android、iOS、Java、Kotlin、Objective-C、Swift、Shell、JavaScript、TypeScript、Python等编程技术的技巧经验分享),若作品对您有帮助,请关注、分享、点赞、收藏、在看、喜欢,您的支持是我们为您提供帮助的最大动力。

http://www.xdnf.cn/news/32401.html

相关文章:

  • matlab 环形单层柱状图
  • 解锁异步JavaScript性能:从事件循环(Event Loop)到Promise与Async/Await的最佳实践
  • 电商平台计算订单成交额是不是要去除退款退货的
  • CMFA在自动驾驶中的应用案例
  • 多线程使用——线程安全、线程同步
  • 【Canvas与旗帜】标准英国米字旗
  • 实现批量图片文字识别(python+flask+EasyOCR)
  • 系统架构设计师:计算机组成与体系结构(如CPU、存储系统、I/O系统)案例分析与简答题、详细解析与评分要点
  • 【C++动态规划】2801. 统计范围内的步进数字数目|2367
  • 洛谷P1177【模板】排序:十种排序算法全解(2)
  • Docker安装与介绍(一)
  • 【工具变量】A股上市公司信息披露质量KV指数测算数据集(含do代码 1991-2024年)
  • 青少年编程与数学 02-016 Python数据结构与算法 29课题、自然语言处理算法
  • 黑马Java基础笔记-1
  • 计算机网络——常见的网络攻击手段
  • 面试题之如何设计一个秒杀系统?
  • 编程语言基础 - C++ 面试题
  • jenkins尾随命令
  • word选中所有的表格——宏
  • ETF价格相关性计算算法深度分析
  • Java Stream 复杂场景排序与分组技术解析与示例代码
  • 蓝桥杯 蜗牛 动态规划
  • 遨游科普:防爆平板是指什么?有哪些应用场景?
  • 使用vue2技术写了一个纯前端的静态网站商城-鲜花销售商城
  • javassist
  • Python concurrent.futures模块的ProcessPoolExecutor, ThreadPoolExecutor类介绍
  • 在 Node.js 中使用原生 `http` 模块,获取请求的各个部分:**请求行、请求头、请求体、请求路径、查询字符串** 等内容
  • Python爬虫实战:获取网易新闻数据
  • Windows系统安装`face_recognition`
  • 2. ubuntu20.04 和VS Code实现 ros的输出 (C++,Python)