《Unity3D高级编程之进阶主程》第一章 C#要点技术(三) 浮点数的精度问题

本文主要是介绍《Unity3D高级编程之进阶主程》第一章 C#要点技术(三) 浮点数的精度问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        浮点数计算在我们大多数项目中并没有使用到特别的科学计算部分,所以float基本都够用。double也同样有精度问题,无论怎么样都是无法避免精度导致的在逻辑中的不一致的问题。

根据 IEEE 754 标准,任意一个二进制浮点数 F 均可表示为:

F = (-1 ^ s) * (1.M) * (2 ^ e)  

  • s:符号位, 0/1
  • M:尾数部分,具体的小数用二进制表示
  • e:比例因子的指数,浮点数的指数

float


      名称

长度        比特位置
符号位Sign(S)1bit(b31)
指数部分Exponent(E)8bit(b30-b23)
尾数部分Mantissa(M)23bit(b22-b0)

 double

名称

长度        比特位置
符号位Sign  (S)1bit  (b63)
指数部分Exponent(E)11bit   (b62-b52)
尾数部分Mantissa(M)52bit    (b51-b0)

        其中E的阶符采用隐含方式,即采用移码(补码)方法来表示正负指数。例如float的8位价码,应将指数e加上一个固定的偏移值127(01111111),即 e 加上 127才是存储在二进制中的数据。

        尾数M只表示1后面的小数部分,而且是二进制直译的那种,然后再根据阶码来平移小数点。

        例:9.625 => 1001.101 => 1.001101×(2^3) => 00110100000000000000000 去掉了小数点左侧的 1,并用 0 在右侧补齐。

        整数部分采用 “除2取余法”,小数部分则采用 “乘2取整法”。

浮点数的精度问题

例:198903.19 
        110000100011110111.0011000010100011(截取 16 位小数)
        198903.19(10) = (-1 ^ 0) * 1.100001000111101110011000010100011 * (2 ^ 17)

      小数部分 0.19 转为二进制后,小数位数超过 16 位(已经手算到小数点后 32 位都还没算完,其实这个位数是无穷尽的),因此这里导致浮点数有诸多精度的问题,它很多时候无法准确的表示数字,甚至非常不准确。

精度问题

         浮点数的精度问题不只是小数点的精度问题,随着数值越来越大,即使是整数也开始会有相同的问题,因为浮点数本身是一个 1.M * (2 ^ e) 公式形式得到的数字,当数字放大时,M的尾数的存储位数没有变化,能表达的位数有限,自然越来越难以准确表达,特别是数字的末尾部分越来越难以准确表达。

常见问题

  1. 数值比较不相等
  2. 数值计算不确定,比如1f / (1f /5555f * 11110f) 结果有可能是0.4999999999991
  3. 不同设备计算结果不同,不同平台上的浮点数计算也有所偏差

解决方案

  1. 只计算一次,认定这个值为准确值,只用这个变量结果做判断,也省去了多次计算浪费的CPU
  2. 改用int或long型来替代浮点数
  3. 用定点数保持一致性并缩小精度问题。定点数把整数部分和小数部分拆分开来,都用整数的形式表示。缺点是由于拆分了整数和小数,两个部分都要占用空间,所以受到存储位数的限制。用定点数来做计算能保证在各设备上的计算结果一致性。
  4. 最耗的办法,用字符串替代浮点数。
  5. 最差的办法,提高期望值。

C# decimal

        它的内部实现就是定点数的实现方式,我们完全可以把它看作定点数来操作。

        它占用128位的存储空间即一个decimal变量占用16个字节。

        它的数值范围在 ±1.0 × 10^28 到 ±7.9 × 10^28之间,这么大的的占用空间却比float的取值范围还小。

        decimal 精度比较大,精度范围在 28 个有效位,另外任何与它一起计算的数值都必须先转化为 decimal 类型否则就会编译报错,数值不会隐式的自动转换成 decimal。

        精度过大导致CPU 计算消耗量大,大量使用时会使得堆栈内存直线飙升,这也间接的增大了CPU的消耗。

        大部分项目自己实现定点数。

这篇关于《Unity3D高级编程之进阶主程》第一章 C#要点技术(三) 浮点数的精度问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1082247

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

2. c#从不同cs的文件调用函数

1.文件目录如下: 2. Program.cs文件的主函数如下 using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using System.Windows.Forms;namespace datasAnalysis{internal static

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

购买磨轮平衡机时应该注意什么问题和技巧

在购买磨轮平衡机时,您应该注意以下几个关键点: 平衡精度 平衡精度是衡量平衡机性能的核心指标,直接影响到不平衡量的检测与校准的准确性,从而决定磨轮的振动和噪声水平。高精度的平衡机能显著减少振动和噪声,提高磨削加工的精度。 转速范围 宽广的转速范围意味着平衡机能够处理更多种类的磨轮,适应不同的工作条件和规格要求。 振动监测能力 振动监测能力是评估平衡机性能的重要因素。通过传感器实时监