广告
返回顶部
首页 > 资讯 > 精选 >float和double运算不精确的原因是什么
  • 326
分享到

float和double运算不精确的原因是什么

2023-06-22 00:06:17 326人浏览 安东尼
摘要

本篇内容主要讲解“float和double运算不精确的原因是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“float和double运算不精确的原因是什么”吧!为什么浮点精度运算会有问题我们平

本篇内容主要讲解“float和double运算不精确的原因是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“float和double运算不精确的原因是什么”吧!

为什么浮点精度运算会有问题

我们平常使用的编程语言大多都有一个问题——浮点型精度运算会不准确。比如

double num = 0.1 + 0.1 + 0.1;// 输出结果为 0.30000000000000004double num2 = 0.65 - 0.6;// 输出结果为 0.05000000000000004

笔者在测试的时候发现 C/C++ 竟然不会出现这种问题,我最初以为是编译器优化,把这个问题解决了。但是 C/c++ 如果能解决其他语言为什么不跟进?根据这个问题的产生原因来看,编译器优化解决这个问题逻辑不通。后来发现是打印的方法有问题,打印输出方法会四舍五入。使用 printf("%0.17f\n", num); 以及 cout << setprecision(17) << num2 << endl; 多打印几位小数即可看到精度运算不准确的问题。

那么精度运算不准确这是为什么呢?

我们接下来就需要从计算机所有数据的表现形式二进制说起了。如果大家很了解二进制与十进制的相互转换,那么就能轻易的知道精度运算不准确的问题原因是什么了。如果不知道就让我们一起回顾一下十进制与二进制的相互转换流程。

一般情况下二进制转为十进制我们所使用的是按权相加法。十进制转二进制是除2取余,逆序排列法。很熟的同学可以略过。

// 二进制到十进制10010 = 0 * 2^0 + 1 * 2^1 + 0 * 2^2 + 0 * 2^3 + 1 * 2^4 = 18   // 十进制到二进制18 / 2 = 9 .... 0 9 / 2 = 4 .... 1 4 / 2 = 2 .... 0 2 / 2 = 1 .... 0 1 / 2 = 0 .... 1 10010

那么,问题来了十进制小数和二进制小数是如何相互转换的呢?

十进制小数到二进制小数一般是整数部分除 2 取余,逆序排列,小数部分使用乘 2 取整数位,顺序排列。二进制小数到十进制小数还是使用按权相加法。

// 二进制到十进制10.01 = 1 * 2^-2 + 0 * 2^-1 + 0 * 2^0 + 1 * 2^1 = 2.25 // 十进制到二进制// 整数部分2 / 2 = 1 .... 01 / 2 = 0 .... 1// 小数部分0.25 * 2 = 0.5 .... 0 0.5 * 2 = 1 .... 1  // 结果 10.01

转小数我们也了解了,接下来我们回归正题,为什么浮点运算会有精度不准确的问题。接下来我们看一个简单的例子 2.1 这个十进制数转成二进制是什么样子的。

2.1 分成两部分// 整数部分2 / 2 = 1 .... 01 / 2 = 0 .... 1 // 小数部分0.1 * 2 = 0.2 .... 00.2 * 2 = 0.4 .... 00.4 * 2 = 0.8 .... 00.8 * 2 = 1.6 .... 10.6 * 2 = 1.2 .... 10.2 * 2 = 0.4 .... 00.4 * 2 = 0.8 .... 00.8 * 2 = 1.6 .... 10.6 * 2 = 1.2 .... 10.2 * 2 = 0.4 .... 00.4 * 2 = 0.8 .... 00.8 * 2 = 1.6 .... 10.6 * 2 = 1.2 .... 1............

落入无限循环结果为 10.0001100110011........ , 我们的计算机在存储小数时肯定是有长度限制的,所以会进行截取部分小数进行存储,从而导致计算机存储的数值只能是个大概的值,而不是精确的值。

从这里看出来我们的计算机根本就无法使用二进制来精确的表示 2.1 这个十进制数字的值,连表示都无法精确表示出来,计算肯定是会出现问题的。

精度运算丢失的解决办法

现有有三种办法

  • 如果业务不是必须非常精确的要求可以采取四舍五入的方法来忽略这个问题。

  • 转成整型再进行计算。

  • 使用 BCD 码存储和运算二进制小数(感兴趣的同学可自行搜索学习)。

一般每种语言都用高精度运算的解决方法(比一般运算耗费性能),比如 python 的 decimal 模块,Java 的 BigDecimal,但是一定要把小数转成字符串传入构造,不然还是有坑,其他语言大家可以自行寻找一下。

Python 示例from decimal import Decimal num = Decimal('0.1') + Decimal('0.1') + Decimal('0.1')print(num)
// Java 示例import java.math.BigDecimal; BigDecimal add = new BigDecimal("0.1").add(new BigDecimal("0.1")).add(new BigDecimal("0.1"));System.out.println(add);

拓展:详解浮点型

上面既然提到了浮点型的存储是有限制,那么我们看一下我们的计算机是如何存储浮点型的,是不是真的正如我们上面提到的有小数长度的限制。

那我们就以 Float 的数据存储结构来说,根据 IEEE 标准浮点型分为符号位,指数位和尾数位三部分(各部分大小详情见下图)。

float和double运算不精确的原因是什么

IEEE 754 标准

一般情况下我们表示一个很大或很小的数通常使用科学记数法,例如:1000.00001 我们一般表示为 1.00000001 * 10^3,或者 0.0001001 一般表示为 1.001 * 10^-4。

符号位

0 是正数,1 是负数

指数位

指数很有意思因为它需要表示正负,所以人们创造了一个叫 EXCESS 的系统。这个系统是什么意思呢?它规定 最大值 / 2 - 1 表示指数为 0。我们使用单精度浮点型举个例子,单精度浮点型指数位一共有八位,表示的十进制数最大就是 255。那么 255 / 2 - 1 = 127,127 就代表指数为 0。如果指数位存储的十进制数据为 128 那么指数就是 128 - 127 = 1,如果存储的为 126,那么指数就是 126 - 127 = -1。

尾数位

比如上述例子中 1.00000001 以及 1.001 就属于尾数,但是为什么叫尾数呢?因为在二进制中比如 1.xx 这个小数,小数点前面的 1 是永远存在的,存了也是浪费空间不如多存一位小数,所以尾数位只会存储小数部分。也就是上述例子中的 00000001 以及 001 存储这样的数据。

float和double运算不精确的原因是什么

IEEE 754 标准

通过上述程序我们得到的存储 1.25 的 float 二进制结构的具体值为 00111111101000000000000000000000 ,我们拆分一下 0 为符号位他是个正值。01111111 为指数位,01000000000000000000000 是尾数。接下来我们验证一下 01111111 转为十进制是 127,那么经过计算指数为 0。尾数是 01000000000000000000000 加上默认省略的 1 为 1.01(省略后面多余的 0),转换为十进制小数就是 1.25。

到此,相信大家对“float和double运算不精确的原因是什么”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: float和double运算不精确的原因是什么

本文链接: https://www.lsjlt.com/news/301728.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • float和double运算不精确的原因是什么
    本篇内容主要讲解“float和double运算不精确的原因是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“float和double运算不精确的原因是什么”吧!为什么浮点精度运算会有问题我们平...
    99+
    2023-06-22
  • 详谈浮点精度(float、double)运算不精确的原因
    目录为什么浮点精度运算会有问题精度运算丢失的解决办法拓展:详解浮点型为什么浮点精度运算会有问题 我们平常使用的编程语言大多都有一个问题——浮点型精度运算会不准确。比如 doubl...
    99+
    2022-11-12
  • java浮点精度运算不精确的原因有哪些
    Java浮点数运算不精确的原因主要有以下几点:1. 浮点数的表示方式:Java中的浮点数类型(float和double)采用的是IE...
    99+
    2023-08-16
    java
  • JS中小数相加不精确的原因是什么
    这篇文章主要介绍“JS中小数相加不精确的原因是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“JS中小数相加不精确的原因是什么”文章能帮助大家解决问题。Javascript中小数相加的问题在Jav...
    99+
    2023-07-06
  • PHP float不准的原因是什么及怎么避免
    今天小编给大家分享一下PHP float不准的原因是什么及怎么避免的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、为什么f...
    99+
    2023-07-05
  • float元素不能指定margin和padding等属性的原因是什么
    这篇文章主要为大家展示了“float元素不能指定margin和padding等属性的原因是什么”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“float元素不能指...
    99+
    2022-10-19
  • float元素的父元素不能指定clear属性是什么原因
    小编给大家分享一下float元素的父元素不能指定clear属性是什么原因,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧! ...
    99+
    2022-10-19
  • sublime text不能运行php的原因是什么和怎么解决
    本篇内容主要讲解“sublime text不能运行php的原因是什么和怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“sublime text不能运行php的原因是什么和怎么解决”吧!一、...
    99+
    2023-07-05
  • js和php文件运行不了的原因是什么及怎么解决
    本文小编为大家详细介绍“js和php文件运行不了的原因是什么及怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“js和php文件运行不了的原因是什么及怎么解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一...
    99+
    2023-07-05
  • 有些时候Python中乘法比位运算更快的原因是什么
    这篇文章主要介绍“有些时候Python中乘法比位运算更快的原因是什么”,在日常操作中,相信很多人在有些时候Python中乘法比位运算更快的原因是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”有些时候Pyt...
    99+
    2023-06-16
  • crontab不执行的原因和解决方案是什么
    crontab不执行的原因有很多,以下是一些可能的原因和解决方案:1. crontab配置错误:可能是crontab的时间设置有误,...
    99+
    2023-08-12
    crontab
  • 不在分页中使用offset和limit的原因是什么
    这篇文章主要讲解了“不在分页中使用offset和limit的原因是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“不在分页中使用offset和limit的...
    99+
    2022-10-19
  • apache调用不起来php5.6的原因和解决方法是什么
    这篇文章主要介绍“apache调用不起来php5.6的原因和解决方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“apache调用不起来php5.6的原因和解决方法是什么”文章能帮助大家解决问...
    99+
    2023-07-05
  • thinkphp中类不存在的三种原因和解决方法是什么
    这篇“thinkphp中类不存在的三种原因和解决方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“thinkphp中类...
    99+
    2023-07-05
  • php7找不到sql server驱动的原因和解决方法是什么
    这篇“php7找不到sql server驱动的原因和解决方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“php7找不...
    99+
    2023-07-05
  • php生成的图片不显示的原因和解决方法是什么
    本篇内容介绍了“php生成的图片不显示的原因和解决方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、文件路径错误在PHP动态生成图...
    99+
    2023-07-05
  • php文件不能输出结果的原因和解决方法是什么
    这篇文章主要讲解了“php文件不能输出结果的原因和解决方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“php文件不能输出结果的原因和解决方法是什么”吧!一、PHP输出的原理在介绍问题...
    99+
    2023-07-05
  • gitlab一段时间ssh不起作用的原因和解决方法是什么
    这篇文章主要介绍“gitlab一段时间ssh不起作用的原因和解决方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“gitlab一段时间ssh不起作用的原因和解决方法是什么”文章能帮助大家解决问...
    99+
    2023-07-05
  • Linux下du -sh和ls -lh显示磁盘占用不一样的原因是什么
    这篇文章将为大家详细讲解有关Linux下du -sh和ls -lh显示磁盘占用不一样的原因是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。原因du -sh *计算的是文件存储到磁盘中占用了多少空间,计...
    99+
    2023-06-15
  • php反向代理不能访问的常见原因和解决方法是什么
    这篇“php反向代理不能访问的常见原因和解决方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“php反向代理不能访问的...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作