定点数运算库

帧同步定点数运算库 --- 设计与使用文档

版本 : 1.0

目标框架 : .NET Standard 2.0(兼容 Unity 2017.1+)

用途: 帧同步(确定性锁步)游戏逻辑层的定点数学运算


目录

  • [帧同步定点数运算库 --- 设计与使用文档](#帧同步定点数运算库 — 设计与使用文档)
    • 目录
    • [1. 概述](#1. 概述)
    • [2. 项目结构](#2. 项目结构)
    • [3. 核心类型:FixedInt](#3. 核心类型:FixedInt)
      • [3.1 内部表示](#3.1 内部表示)
      • [3.2 构造函数](#3.2 构造函数)
      • [3.3 类型转换](#3.3 类型转换)
      • [3.4 算术运算符](#3.4 算术运算符)
      • [3.5 比较运算符](#3.5 比较运算符)
      • [3.6 位移运算符](#3.6 位移运算符)
      • [3.7 属性](#3.7 属性)
      • [3.8 静态常量](#3.8 静态常量)
    • [4. 三维向量:FixedVector3](#4. 三维向量:FixedVector3)
      • [4.1 构造与分量访问](#4.1 构造与分量访问)
      • [4.2 静态方向向量](#4.2 静态方向向量)
      • [4.3 向量运算](#4.3 向量运算)
      • [4.4 静态工具方法](#4.4 静态工具方法)
      • [4.5 Unity 互操作](#4.5 Unity 互操作)
    • [5. 角度类型:Args](#5. 角度类型:Args)
      • [5.1 设计动机](#5.1 设计动机)
      • [5.2 静态常量](#5.2 静态常量)
      • [5.3 比较运算](#5.3 比较运算)
      • [5.4 格式转换](#5.4 格式转换)
    • [6. 数学工具:Calc](#6. 数学工具:Calc)
      • [6.1 Abs --- 绝对值](#6.1 Abs — 绝对值)
      • [6.2 Sqrt --- 平方根](#6.2 Sqrt — 平方根)
      • [6.3 Acos --- 反余弦](#6.3 Acos — 反余弦)
      • [6.4 Clamp --- 钳制](#6.4 Clamp — 钳制)
    • [7. 查表实现:AcosTable](#7. 查表实现:AcosTable)
    • [8. 设计原理与关键决策](#8. 设计原理与关键决策)
      • [8.1 缩放因子的选择:1024 (2^10)](#8.1 缩放因子的选择:1024 (2^10))
      • [8.2 负数的向零截断](#8.2 负数的向零截断)
      • [8.3 类型分离防止单位混淆](#8.3 类型分离防止单位混淆)
      • [8.4 查表 vs 实时计算](#8.4 查表 vs 实时计算)
      • [8.5 牛顿法的迭代次数](#8.5 牛顿法的迭代次数)
    • [9. 使用示例](#9. 使用示例)
      • [9.1 基本算数](#9.1 基本算数)
      • [9.2 向量运算](#9.2 向量运算)
      • [9.3 数学函数](#9.3 数学函数)
      • [9.4 Unity 集成(帧同步游戏典型模式)](#9.4 Unity 集成(帧同步游戏典型模式))
      • [9.5 网络序列化](#9.5 网络序列化)
    • [10. 局限性与扩展方向](#10. 局限性与扩展方向)
    • 附录:关键常量速查

1. 概述

本库是一个完全确定性的定点数数学库,专为帧同步(锁步同步)多人游戏设计。

为什么要用定点数? 在帧同步架构中,所有客户端必须独立计算出完全一致的结果。IEEE 754 浮点数在不同 CPU 架构、不同编译器优化级别下,舍入行为可能不同(如 x87 vs SSE 指令集),导致计算结果出现微小偏差,进而破坏帧同步的一致性。定点数以整数为基础进行运算,在所有平台上保证比特级一致。

核心设计特点:

特点 说明
整数运算 所有运算基于 long(64位有符号整数),跨平台结果一致
双缩放因子 距离量使用 1024 缩放,角度量使用 10000 缩放,防止单位混淆
查表法三角函数 arccos 使用 1025 条目的预计算表,O(1) 时间复杂度 + 确定性
牛顿法开方 平方根使用牛顿-拉弗森迭代,可控精度/性能权衡
Unity 互操作 条件编译支持与 UnityEngine.Vector3 双向转换
零分配 所有类型均为 struct,不产生 GC 压力

2. 项目结构

复制代码
FixedMath/
├── FixedMath/
│   ├── FixedMath.csproj                  # 核心库项目 (netstandard2.0)
│   ├── FixedInt.cs                       # 定点数结构体
│   ├── FixedVector3.cs                   # 定点数三维向量
│   ├── Args.cs                           # 角度/三角函数结果包装
│   ├── Calc.cs                           # 数学工具类 (sqrt, acos, clamp, abs)
│   └── AcosTable.cs                      # 反余弦预计算查找表 (internal)
└── FixedMathTest/
    └── FixedMathTest.cs                  # 7 个测试用例

类型一览:

类型 访问级别 种类 说明
FixedInt public struct 值类型 核心定点数
FixedVector3 public struct 值类型 三维定点向量
Args public struct 值类型 角度测量结果
Calc public class 静态工具类 数学函数集合
AcosTable internal class 静态数据类 arccos 查找表(内部实现)

3. 核心类型:FixedInt

3.1 内部表示

FixedIntlong scaledValue 存储数值,真实值 = scaledValue / 1024

复制代码
缩放因子:MULTIPLIER_FACTOR = 1024 = 2^10
位移位数:BIT_MOVE_COUNT = 10

真实值 1.0  →  scaledValue = 1024
真实值 3.5  →  scaledValue = 3584  (3.5 × 1024)
真实值 0.0  →  scaledValue = 0

精度1 / 1024 ≈ 0.0009765625,约小数点后 3 位有效精度。

范围long 型取值范围为 [-2^63, 2^63-1],因此代表真实值的范围为:

复制代码
最小值 ≈ -9.0 × 10^15
最大值 ≈ +9.0 × 10^15

完全满足游戏场景中的位置、速度、血量等数值需求。

3.2 构造函数

构造函数 说明 精度
FixedInt(int val) 整数 → 定点数,scaledValue = val × 1024 无损(整数在范围内精确表达)
FixedInt(float val) 浮点 → 定点数,scaledValue = Round(val × 1024) 四舍五入,精度损失 ≤ 0.5/1024 ≈ 0.0005
csharp 复制代码
// 从整数创建(推荐:无精度损失)
FixedInt a = new FixedInt(3);    // scaledValue = 3072

// 从浮点创建(仅用于编辑器配置导入等场景)
FixedInt b = new FixedInt(3.5f); // scaledValue = 3584

3.3 类型转换

转换 方式 示例
intFixedInt 隐式(implicit) FixedInt a = 3;
floatFixedInt 显式(explicit) FixedInt b = (FixedInt)3.5f;
csharp 复制代码
// 隐式转换:int → FixedInt,无精度损失
FixedInt health = 100;

// 显式转换:float → FixedInt,需要显式强制转换
FixedInt speed = (FixedInt)5.5f;

// FixedInt → float(仅用于显示层,非确定性)
float displayValue = speed.RawFloat;

// FixedInt → int(截断取整)
int intPart = speed.RawInt;

⚠️ 重要float 转换始终伴随精度损失,应在逻辑帧中使用 FixedInt 之间的运算,仅在表现层 (渲染、UI 显示)才转换为 float

3.4 算术运算符

所有运算符返回新的 FixedInt,不修改原值(不可变语义)。

运算符 签名 底层实现 备注
+ a + b a.SV + b.SV 直接加缩放值
- a - b a.SV - b.SV 直接减缩放值
* a * b (a.SV × b.SV) >> 10 乘后右移消除多余缩放因子
/ a / b (a.SV << 10) / b.SV 先左移保留精度再除
- (取负) -a -a.SV 取反缩放值

SV = ScaledValue(内部缩放值)

乘法原理详解:

复制代码
(a × 1024) × (b × 1024) = (a×b) × 1024^2
结果需要右移 10 位 → (a×b) × 1024 ✓

对于负数,库使用 取反→右移→再取反 的技巧,确保向零截断(而非向负无穷),与 C# 浮点除法行为一致。

除法原理详解:

复制代码
(a × 1024) << 10 = (a × 1024) × 1024 = a × 1024^2
除以 (b × 1024) → (a/b) × 1024 ✓

先左移再除保留了小数精度,避免整数除法的截断误差。

3.5 比较运算符

所有比较直接对 scaledValue 进行,高效且确定。

csharp 复制代码
public static bool operator ==(FixedInt a, FixedInt b)  // a.SV == b.SV
public static bool operator !=(FixedInt a, FixedInt b)  // a.SV != b.SV
public static bool operator > (FixedInt a, FixedInt b)  // a.SV >  b.SV
public static bool operator < (FixedInt a, FixedInt b)  // a.SV <  b.SV
public static bool operator >=(FixedInt a, FixedInt b)  // a.SV >= b.SV
public static bool operator <=(FixedInt a, FixedInt b)  // a.SV <= b.SV

同时覆写了 Equals(object)GetHashCode(),保证相等语义一致。

3.6 位移运算符

运算符 效果 等价于
a >> n 算术右移 n 位 a / (2^n)(向零截断)
a << n 左移 n 位 a × (2^n)

负数右移使用 取反→移位→再取反 处理,避免 C# 算术右移对负数补符号位(向负无穷截断)导致的逻辑差异。

csharp 复制代码
FixedInt a = 8;       // SV = 8192
FixedInt b = a >> 2;  // SV = 2048,真实值 = 2.0

3.7 属性

属性 类型 说明
ScaledValue long (get/set) 内部缩放值,用于序列化或自定义扩展
RawFloat float (get) 近似浮点值 = SV / 1024.0f。仅用于表现层
RawInt int (get) 截断取整的整数部分。负数向零截断
Abs FixedInt (get) 返回绝对值
csharp 复制代码
FixedInt a = (FixedInt)(-3.5f);
Console.WriteLine(a.ScaledValue);  // -3584
Console.WriteLine(a.RawFloat);     // -3.5
Console.WriteLine(a.RawInt);       // -3 (向零截断)
Console.WriteLine(a.Abs.RawFloat); // 3.5

3.8 静态常量

csharp 复制代码
public static readonly FixedInt zero = new FixedInt(0);   // SV = 0,  真实值 = 0
public static readonly FixedInt one  = new FixedInt(1);   // SV = 1024, 真实值 = 1

4. 三维向量:FixedVector3

4.1 构造与分量访问

csharp 复制代码
// 三个定点分量构造
FixedvVector3 position = new FixedVector3(
    (FixedInt)10.5f,  // x
    (FixedInt)0,      // y
    (FixedInt)(-3.0f) // z
);

// 索引器访问
FixedInt x = position[0];   // 等价于 position.x
FixedInt y = position[1];   // 等价于 position.y
FixedInt z = position[2];   // 等价于 position.z
position[0] = (FixedInt)5;  // 修改 x 分量

4.2 静态方向向量

csharp 复制代码
FixedVector3.zero      // ( 0,  0,  0)
FixedVector3.one       // ( 1,  1,  1)
FixedVector3.forward   // ( 0,  0,  1)
FixedVector3.back      // ( 0,  0, -1)
FixedVector3.left      // (-1,  0,  0)
FixedVector3.right     // ( 1,  0,  0)
FixedVector3.up        // ( 0,  1,  0)
FixedVector3.down      // ( 0, -1,  0)

4.3 向量运算

运算符/属性 示例 说明
+ v1 + v2 分量加法
- v1 - v2 分量减法
-v -v1 取反
* v * scalarscalar * v 标量乘法
/ v / scalar 标量除法
== / != v1 == v2 全分量比较
.sqrMagnitude --- x² + y² + z²(平方长度)
.magnitude --- Sqrt(x² + y² + z²)(向量长度)
.normalized --- 单位向量(长度=1),零向量返回 zero

归一化实现优化

csharp 复制代码
// 归一化使用 "乘以倒数" 而非 "三次除法"
// 一次除法算倒数 + 三次乘法,远快于三次除法
FixedInt invMag = FixedInt.one / magnitude;
return new FixedVector3(x * invMag, y * invMag, z * invMag);

4.4 静态工具方法

方法 签名 说明
SqrMagnitude FixedInt SqrMagnitude(FixedVector3 v) 静态版平方长度
Normalize FixedVector3 Normalize(FixedVector3 v) 静态版归一化,返回新向量
Normalize() void Normalize() 实例方法,原地归一化(修改自身)
Dot FixedInt Dot(FixedVector3 a, FixedVector3 b) 点积:ax×bx + ay×by + az×bz
Cross FixedVector3 Cross(FixedVector3 a, FixedVector3 b) 叉积:a × b
Angle Args Angle(FixedVector3 from, FixedVector3 to) 两向量夹角,通过 arccos 查表

叉积公式(标准右手坐标系):

复制代码
Cross(a, b) = (
    ay×bz - az×by,   // x
    az×bx - ax×bz,   // y
    ax×by - ay×bx    // z
)

夹角计算流程

复制代码
cosθ = Dot(from, to) / (|from| × |to|)
θ = Acos(cosθ)  ← 查表 O(1)

若存在零向量(长度为 0),返回 Args.Zero

4.5 Unity 互操作

通过条件编译 #if UNITY_2017_1_OR_NEWER 提供:

csharp 复制代码
// Unity → FixedMath(逻辑帧初始化时)
Vector3 unityPos = transform.position;
FixedVector3 logicPos = new FixedVector3(unityPos);

// FixedMath → Unity(表现层同步时)
FixedVector3 logicPos = GetLogicPosition();
Vector3 unityPos = logicPos.ConvertViewVector3();

此外提供 CovertLongArray() 导出为 long[3],用于网络传输或序列化:

csharp 复制代码
long[] rawData = vector.CovertLongArray();
// rawData = { x.ScaledValue, y.ScaledValue, z.ScaledValue }

5. 角度类型:Args

5.1 设计动机

Args 使用独立的缩放因子 10000 (不同于 FixedInt 的 1024),核心原因是防止距离/位置量与角度量在做乘除运算时意外混淆 。如果你用同一个 FixedInt 类型表示距离和角度,以下代码不会报错:

csharp 复制代码
FixedInt distance = 5;
FixedInt angle = 3;
FixedInt result = distance * angle;  // 编译通过,但逻辑上无意义!

Args 使用独立类型 + 独立缩放因子,从类型系统层面杜绝此类错误。

复制代码
Args.value / multipler = 实际弧度值
例如:PI = 31416 / 10000 = 3.1416 弧度

5.2 静态常量

csharp 复制代码
Args.Zero    = new Args(0,     10000);  // 0 弧度 = 0°
Args.HALFPI  = new Args(15708, 10000);  // π/2 = 1.5708 弧度 = 90°
Args.PI      = new Args(31416, 10000);  // π = 3.1416 弧度 = 180°
Args.TWOPI   = new Args(62832, 10000);  // 2π = 6.2832 弧度 = 360°

5.3 比较运算

所有比较运算符(>, <, >=, <=, ==, !=)均要求两个 Argsmultipler 相同,否则抛出异常。正常情况下不会触发(所有角度都使用 multiplier=10000)。

5.4 格式转换

csharp 复制代码
Args angle = Calc.Acos(FixedInt.zero);  // acos(0) = π/2

// 转为浮点弧度(仅显示层)
float radians = angle.ConvertToFloat();     // ≈ 1.5708f

// 转为整数度数(四舍五入)
int degrees = angle.ConvertViewAngle();     // = 90

6. 数学工具:Calc

6.1 Abs --- 绝对值

csharp 复制代码
FixedInt result = Calc.Abs(value);

直接在原值的 ScaledValue 上取反。等效于 .Abs 属性,但以静态方法形式提供。

6.2 Sqrt --- 平方根

csharp 复制代码
FixedInt result = Calc.Sqrt(value, interatorCount = 8);

算法:牛顿-拉弗森迭代法(Newton-Raphson)

复制代码
初始猜测: x₀ = value
迭代公式: x_{n+1} = (x_n + value / x_n) / 2
终止条件: x_{n+1} == x_n(收敛)或达到最大迭代次数
  • 零值直接返回 0
  • 负数抛出异常(无实数平方根)
  • /2>> 1 实现(位运算加速)
  • 默认最大 8 次迭代,平衡精度与性能
csharp 复制代码
Calc.Sqrt(25);      // → 5
Calc.Sqrt(2);       // → ≈ 1.414(SV = 1448)
Calc.Sqrt(0);       // → 0
Calc.Sqrt(10000);   // → ≈ 100

6.3 Acos --- 反余弦

csharp 复制代码
Args result = Calc.Acos(FixedInt value);

输入范围[-1, 1](自动钳制,越界不抛异常)

算法:查表法(详见第 7 节)

复制代码
1. 将输入 value ∈ [-1, 1] 线性映射到表索引 [0, 1024]:
   input = value × 512 + 512

2. 钳制索引到 [0, 1024]

3. 查表: table[index] → 弧度 × 10000

4. 包装为 Args(value, 10000)

关键映射点:

输入 cos 值 索引 表值 实际弧度
-1.0 0 31416 π ≈ 3.1416
-0.5 256 --- 2π/3 ≈ 2.0944
0.0 512 15708 π/2 ≈ 1.5708
0.5 768 --- π/3 ≈ 1.0472
1.0 1024 0 0

6.4 Clamp --- 钳制

csharp 复制代码
FixedInt result = Calc.Clamp(input, min, max);
csharp 复制代码
Calc.Clamp(10, 0, 5);  // → 5
Calc.Clamp(-2, 0, 5);  // → 0
Calc.Clamp(3, 0, 5);   // → 3

7. 查表实现:AcosTable

AcosTableinternal class,对外不可见。它提供了反余弦的 O(1) 确定性实现。

属性
条目数 (IndexCount) 1024
半表条目 (HalfIndexCount) 512(用于 -1,10,1024 映射)
数组长度 1025(索引 0~1024)
缩放因子 (Multipler) 10000
内存占用 1025 × 4 = 4.1 KB
覆盖范围 cos ∈ -1.0, 1.0,均匀步长 2.0/1024 ≈ 0.00195

预计算方式(在静态构造函数中硬编码):

复制代码
table[i] = round(acos(-1.0 + i × 2.0/1024) × 10000)

将 1025 个值直接硬编码为 int[] 初始化器,避免运行时触发浮点运算,保证:

  1. 跨平台一致性:所有平台用同一份硬编码表
  2. 零初始化开销:数据在程序集加载时即就位
  3. 无运行时浮点依赖:逻辑帧不执行任何浮点运算

8. 设计原理与关键决策

8.1 缩放因子的选择:1024 (2^10)

选择 2 的幂作为缩放因子,使得乘除法的缩放调整可以用位移实现

复制代码
乘法后 descale: >> 10  (比整数除法快)
除数前 upscale: << 10  (比整数乘法快)

10 位精度在游戏中提供约 0.001 的分辨率,对于位置(通常以米/厘米为单位)、速度、血量等足够使用。

8.2 负数的向零截断

C# 中 long 的算术右移(>>)对负数会补 1(向负无穷截断)。例如 -3 >> 1 = -2(期望 -1,向零截断)。

库中对所有涉及负数的右移使用统一模式:

csharp 复制代码
num = ((num < 0) ? (-(-num >> 10)) : (num >> 10));
// 取反 → 正数右移 → 再取反 = 向零截断

保证了运算结果在各平台上与浮点数学语义一致。

8.3 类型分离防止单位混淆

数量类别 类型 缩放因子
距离、位置、速度 FixedInt 1024
角度(弧度) Args 10000

两个类型不直接兼容(无隐式/显式转换),防止将角度误用于位置运算。

8.4 查表 vs 实时计算

对于反余弦这类超越函数,实时计算(如泰勒级数、CORDIC)需要多次迭代且难以保证跨平台一致性。查表法用约 4KB 内存换取:

  • O(1) 恒定时间复杂度
  • 100% 跨平台确定性
  • 零运行时浮点计算

8.5 牛顿法的迭代次数

Sqrt 默认 8 次迭代。牛顿法具有二次收敛性,在游戏场景的常见数值范围内,通常 5-6 次即可收敛。8 次是保守上限。


9. 使用示例

9.1 基本算数

csharp 复制代码
// 创建定点数
FixedInt a = 3;                    // 隐式从 int
FixedInt b = (FixedInt)2.5f;       // 显式从 float
FixedInt c = FixedInt.one;         // 静态常量

// 四则运算
FixedInt sum = a + b;              // 3 + 2.5 = 5.5
FixedInt diff = a - b;             // 3 - 2.5 = 0.5
FixedInt prod = a * b;             // 3 × 2.5 = 7.5
FixedInt quot = a / b;             // 3 ÷ 2.5 = 1.2

// 比较
if (a > b) { /* ... */ }
if (sum == (FixedInt)5.5f) { /* 注意:浮点转换可能引入误差 */ }

9.2 向量运算

csharp 复制代码
// 创建向量
FixedVector3 pos = new FixedVector3(0, 0, 0);
FixedVector3 dir = new FixedVector3((FixedInt)1.5f, 0, (FixedInt)2.0f);

// 向量归一化
FixedVector3 unitDir = dir.normalized;

// 移动:位置 = 原位置 + 方向 × 速度 × 时间
FixedInt speed = (FixedInt)5.0f;
FixedInt dt = (FixedInt)(1.0f / 60.0f);  // 60 FPS 逻辑帧
FixedVector3 newPos = pos + unitDir * speed * dt;

// 点积判断朝向
FixedInt dotProduct = FixedVector3.Dot(dir, FixedVector3.forward);
bool isFacingForward = dotProduct > FixedInt.zero;

// 夹角
Args angle = FixedVector3.Angle(FixedVector3.forward, dir);
int degrees = angle.ConvertViewAngle();  // 查看多少度

9.3 数学函数

csharp 复制代码
// 绝对值
FixedInt absVal = Calc.Abs((FixedInt)(-10.5f));  // 10.5

// 平方根(距离计算常用)
FixedInt distance = FixedVector3.SqrMagnitude(from - to);
FixedInt dist = Calc.Sqrt(distance);

// 钳制(血量不低于 0、不超上限)
FixedInt health = Calc.Clamp(currentHealth, FixedInt.zero, maxHealth);

// 反余弦(获取角度)
Args angle = Calc.Acos(FixedInt.one);       // acos(1) = 0 弧度
Args angle2 = Calc.Acos(FixedInt.zero);      // acos(0) = π/2 弧度
Args angle3 = Calc.Acos((FixedInt)(-1.0f)); // acos(-1) = π 弧度

9.4 Unity 集成(帧同步游戏典型模式)

csharp 复制代码
// ===== 逻辑层(所有客户端独立执行,结果必须一致)=====
public class LogicBattleSystem
{
    FixedVector3 playerPos;
    FixedVector3 playerVelocity;
    FixedInt moveSpeed = (FixedInt)5.0f;

    public void LogicUpdate(FixedInt deltaTime)
    {
        // 所有运算基于 FixedInt,完全确定
        playerPos = playerPos + playerVelocity * deltaTime;
        playerVelocity = playerVelocity * (FixedInt)0.98f;  // 阻尼
    }
}

// ===== 表现层(仅渲染用,不参与逻辑)=====
public class ViewBattleSystem : MonoBehaviour
{
    LogicBattleSystem logic;

    void Update()
    {
        // 从逻辑层同步到表现层
        Vector3 renderPos = logic.playerPos.ConvertViewVector3();
        transform.position = Vector3.Lerp(
            transform.position, renderPos, Time.deltaTime * 10f);
    }
}

// ===== 初始化:从 Unity 场景导入初始位置 =====
void Start()
{
    logic.playerPos = new FixedVector3(transform.position);
}

9.5 网络序列化

csharp 复制代码
// 发送端:导出原始缩放值
long[] posData = playerPos.CovertLongArray();
SendToNetwork(posData); // { x.ScaledValue, y.ScaledValue, z.ScaledValue }

// 接收端:从缩放值重建
long[] receivedData = ReceiveFromNetwork();
FixedVector3 syncedPos = new FixedVector3(
    new FixedInt(receivedData[0]),  // 注意:这是 private 构造函数
);

⚠️ 当前 FixedInt(long scaledValue) 构造函数是 private,外部无法直接以缩放值构造。如需支持序列化反序列化,需要对 FixedInt 添加 public 的缩放值构造函数。


10. 局限性与扩展方向

当前局限

局限 影响
Vector2 2D 游戏需手动模拟或用 FixedVector3(z=0)
无矩阵/四元数 旋转只能通过角度+方向向量实现
无 sin/cos/tan/atan 仅支持 acos,无法直接计算三角函数
Lerp/Slerp 缺乏插值工具,需手动实现
无随机数生成器 缺乏确定性 PRNG,需自行集成
FixedInt(long) 私有 不便于从缩放值序列化重建
Floor/Ceil/Round 缺乏舍入控制
Max/Min 仅有 Clamp
除零异常无信息 仅抛出空 Exception()

推荐扩展

复制代码
高优先级:
├── Vector2(2D 向量)
├── sin / cos 查表实现(可复用 AcosTable 的查表思路)
├── atan / atan2 查表实现
├── FixedInt(long) 改为 public 或提供静态工厂方法
├── 确定性随机数(LCRNG 或 Xorshift)
└── Lerp / MoveTowards

中优先级:
├── Matrix4x4 / 旋转矩阵
├── Quaternion(定点四元数)
├── Floor / Ceil / Round / Max / Min
├── 除零异常携带有意义消息
└── 单元测试项目(当前测试较简单)

低优先级:
├── BoundingBox / AABB
├── Ray / RaycastHit
├── Plane
└── 性能测试基准项目

附录:关键常量速查

常量 说明
MULTIPLIER_FACTOR 1024 FixedInt 缩放因子
BIT_MOVE_COUNT 10 FixedInt 位移位数
AcosTable.IndexCount 1024 查表条目数
AcosTable.Multipler 10000 角度缩放因子
Args.PI.value 31416 π × 10000
Args.HALFPI.value 15708 π/2 × 10000
Args.TWOPI.value 62832 2π × 10000

本文档覆盖 FixedIntFixedVector3ArgsCalcAcosTable 全部公开 API 与内部实现细节。如需了解最新的代码变更,请查看 Git 提交记录。

相关推荐
dyxal1 小时前
最长公共子序列(LCS)
python·算法
稚南城才子,乌衣巷风流4 小时前
ST 表(Sparse Table)算法详解:原理、实现与应用
算法
hold?fish:palm4 小时前
9 找到字符串中所有字母异位词
c++·算法·leetcode
Sw1zzle4 小时前
算法入门(六):贪心算法 - 基础入门(Leetcode 121/455/860/376/738)
算法·leetcode·贪心算法
青山木4 小时前
Hot 100 --- 岛屿数量
java·数据结构·算法·leetcode·深度优先·广度优先
不会就选b5 小时前
算法日常・每日刷题--<归并排序>1
数据结构·算法
危桥带雨5 小时前
排序算法(快排、归并、计数、基数排序)
数据结构·算法·排序算法
啦啦啦啦啦zzzz5 小时前
算法:回溯算法
c++·算法·leetcode