【Unity主程手记(摘录)】第一章(三) - 浮点数的精度问题

文章探讨了浮点数(double和float)在计算机中的精度问题,源于二进制转换和存储限制。当进行数值比较和计算时,可能会遇到不精确的情况。解决办法包括一次计算定值、转换为整数、使用定点数或decimal类型,甚至字符串表示。举例说明了如何通过策略避免精度误差。
摘要由CSDN通过智能技术生成

第一章(三) - 浮点数的精度问题

提示:个人学习总结,如有错误,敬请指正。



一、double和float

1.原因

转换成二进制位数位数太长超过了存储位数,必须舍弃多余的位数,造成了精度损失。

计算机组成原理(定点数和浮点数边表示)


2.浮点数如何转换成二进制

在这里插入图片描述

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


3.哪些情况会碰到这类问题

  1. 数值比较不相等
    浮点数在运算时无法准确定位到某个值,比如要么比0.23小,要么比他大,这样就不能使用==来做检查而是使用>、<,如果要用等于,则必须使用一个很小的浮动区间,abs(X-Y) <0.00001,即X -Y >float.Epsilon。
  2. 数值计算不确定
    浮点数由于位数限制无法得到一个精确的数值,而是一个被截断的值,在某些情况期望的结果是1,但算出来可能是0.9999999999。
  3. 设备不同,不同平台和架构会导致浮点数的精度不一致

4.解决办法

  • 只计算一次,认定这个值为准确值,只用这个变量结果做判断,也省去了多次计算浪费的CPU。
  • 改用int或long,把浮点数乘以10幂次得到更准确的整数,即把精度用整型表示,比如约定所有浮点数都乘以10000,1.5x10000=15000,用的时候再转回来。
  • 定点数,即把整数位和小数位分开存
    • decimal 并不好用(大部分游戏开发者的首选选择)
    • 把整数和小数拆开来存储,用两个int整数分别表示整数部分和小数部分,或者用long长整型存储(前32位存储整数,后32位存储浮点数),long型存储会更好因为这样就确保定点数的内存就是连续的。这样无论整数还是小数部分都用整数表示,并封装在类中,继而我们需要重载(override)所有的基本计算和比较符号,包括+、-、*、/、==、!=、>、<、>=、<=、这些符号都需要重载,重载范围包括 float浮点数、double双精度、int整数、long长整数等。除了以上这些,为了能更好的融合定点数与外部数据的逻辑计算,我们还需要为此写一些额外的定点库,包括定点数坐标类,定点数Quaternion类等用于定点数的扩展。
  • 字符串代替浮点数,但缺点是CPU和内存消耗大,只能做少量计算
  • 最差的办法,提高期望值
    • 例子:如果 1.55f / 2f 有可能等于 0.7749999 而无法达到 0.775 的目标值时,我们不妨在计算前多加个0.01,使得 1.56f / 2f,这样就大概率保证超出 0.775 的结果目标了

附录

主程手记
乘2取整法

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值