当前位置:   article > 正文

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

unity float精度

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

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



一、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取整法

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/108421
推荐阅读
相关标签
  

闽ICP备14008679号