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

【Unity】什么是定点数?定点数的实现原理(个人复习笔记/侵删/不足之处欢迎斧正)

什么是定点数?定点数的实现原理

什么是定点数?

约定计算机中小数点的位置,且这个位置固定不变,小数点前、后的数字,分别用二进制表示,然后组合起来就可以把这个数字在计算机中存储起来,这种表示方式叫做「定点」表示法,用这种方法表示的数字叫做「定点数」。

什么是定点数?-CSDN博客

在使用帧同步开发中,如果不使用定点数而采用浮点数,会出现各种而样的问题(浮点误差)

真正使用定点数时,基本保留0位小数,完全使用整形数据,误差最小

定点数实现机制?

1.小数定位法:

        固定浮点数的小数点,比如保留一位保留两位,这样会接近真实值。可以进行加减计算,但是涉及到复杂乘除运算时弊端就会暴露,差生了更多的小数

2.乘法放大入整法:

        通过确定放大因子,然后转为整数,之后计算变为完全整数的运算,最后在渲染层需要渲染时除去放大因子,交由渲染层去渲染。但是细节容易出现疏漏,可能会丢失精度

3.位移运算入整法(推荐):

        位移运算只能用于整型数值,因此比较适合在定点数中,位移运算满足二次幂运算,效率较高,速度快。

        如何实现:提前准备一个放大因子,在非定点数类型转为定点数时,左移放大因子

《帧同步定点数》定点数原理和无损精度的实现方式_帧同步 定点数-CSDN博客

移位运算为什么更快?

因为移位指令占2个机器周期,而乘除法指令占4个机器周期。
计算机cpu的移位指令一般单周期就能执行完毕,而其他的指令比如乘法或除法指令都是多周期指令,所以节省了运行时间,导致效率更高的结果。

注意事项?

定点数转换为浮点数之后,浮点数就不应该再参与到帧同步的运算之中。可以说,帧同步的计算不需要转换为浮点数,只有把结果交给UI表现时,才需要转换为浮点数

VINT

using System;

[Serializable]
public struct VInt:IComparable<VInt>
{
    private long i;
    //位移计数
    const int FIX_MULTIPLE = 1024;

    public static readonly VInt one = new VInt((long)FIX_MULTIPLE);
    public int Int { get { return (int)i; } }
    public float RawFloat { get { return (float)this.i * 1.0f / FIX_MULTIPLE; } }
    public int RawInt { get { return (int)i / FIX_MULTIPLE; } }

    private VInt(long i)
    {
        this.i = i;
    }
    public VInt(int i)
    {
        this.i = i * FIX_MULTIPLE;
    }
    public VInt(float f)
    {
        this.i = (int)Math.Round((double)(f * 1.0f * FIX_MULTIPLE));
    }

    public override bool Equals(object o)
    {
        if (o == null)
        {
            return false;
        }
        VInt vInt = (VInt)o;
        return this.i == vInt.i;
    }

    public override int GetHashCode()
    {
        return this.i.GetHashCode();
    }

    public static VInt Min(VInt a, VInt b)
    {
        return new VInt(Math.Min(a.i, b.i));
    }

    public static VInt Max(VInt a, VInt b)
    {
        return new VInt(Math.Max(a.i, b.i));
    }

    public override string ToString()
    {
        return this.RawFloat.ToString();
    }

 

    public int CompareTo(VInt other)
    {
        return i.CompareTo(other.i);
    }

    public static explicit operator VInt(float f)
    {
        return new VInt((int)Math.Round((double)(f * 1.0f * FIX_MULTIPLE)));
    }

    public static implicit operator VInt(int i)
    {

        return new VInt(i);
    }

    public static explicit operator float(VInt ob)
    {
        return (float)ob.i * 1.0f / FIX_MULTIPLE;
    }

    public static explicit operator long(VInt ob)
    {
        return (long)ob.i;
    }

    public static VInt operator +(VInt a, VInt b)
    {
        return new VInt(a.i + b.i);
    }

    public static VInt operator -(VInt a, VInt b)
    {
        return new VInt(a.i - b.i);
    }

    public static VInt operator *(VInt a, VInt b)
    {
        long value = a.i * b.i;
        if (value >= 0)
        {
            value /= FIX_MULTIPLE;
        }
        else
        {
            value = -(-value / FIX_MULTIPLE);
        }
        return new VInt(value);
    }

    public static VInt operator /(VInt a, VInt b)
    {
        return new VInt((a.i * FIX_MULTIPLE / b.i));
    }
    public static bool operator ==(VInt a, VInt b)
    {
        return a.i == b.i;
    }
    public static VInt operator -(VInt a)
    {
        return new VInt(-a.i);
    }

    public static bool operator !=(VInt a, VInt b)
    {
        return a.i != b.i;
    }

    public static bool operator >(VInt a, VInt b)
    {
        return a.i > b.i;
    }
    public static bool operator <(VInt a, VInt b)
    {
        return a.i < b.i;
    }
    public static bool operator >=(VInt a, VInt b)
    {
        return a.i >= b.i;
    }
    public static bool operator <=(VInt a, VInt b)
    {
        return a.i <= b.i;
    }
    public static VInt operator >>(VInt value, int moveCount)
    {
        if (value.i >= 0)
        {
            return new VInt(value.i >> moveCount);
        }
        else
        {
            return new VInt(-(-value.i >> moveCount));
        }

    }
    public static VInt operator <<(VInt value, int moveCount)
    {
        return new VInt(value.i << moveCount);
    }
}


http://www.kler.cn/news/360931.html

相关文章:

  • C++编程语言:抽象机制:特殊运算符(Bjarne Stroustrup)
  • 鸿蒙--应用首次启动
  • Idea插件-arthas idea
  • C++详解
  • 如何解决 IDEA 的 pom.xml 文件中,依赖警告问题
  • Android广播限制Background execution not allowed: receiving Intent { act=
  • CTFHUB技能树之SQL——字符型注入
  • 【NestJS入门到精通】装饰器
  • 【无标题】海尔AI英语面试
  • AIGC时代算法工程师的面试秘籍(第二十四式2024.9.30-10.20) |【三年面试五年模拟】
  • windows 导出 oracle DMP文件
  • 【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,2-2
  • Kadane 算法
  • 【含开题报告+文档+PPT+源码】基于springboot的旅游路线推荐系统的设计与实现
  • 开发自定义大模型
  • 力扣 56.合并区间——Java
  • 让你的 IDEA 使用更流畅 | IDEA内存修改
  • 【GIT】.cr、.gitattributes 、 .gitignore和.git各文件夹讲解介绍
  • 使用milvus数据库实现文本相似比较
  • 打造高性能在线电子表格:WebGL 渲染引擎 Kola2d 自研之路