区块链技术博客
www.b2bchain.cn

S01E23:计算几何中的误差来源分析求职学习资料

D0b2wT.gif

本文介绍了S01E23:计算几何中的误差来源分析求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

说明

从开篇时,我们就遇到过计算精度问题,在前面的代码中,当我们遇到需要判断点是否重合,向量是否平行/垂直,向量是否是零(长度过短),都是笼统地用小于 0.0001 或者 Swift 提供的 Float 类型最小值Float.leastNormalMagnitude来简单判断。

事实上,这些是不合理的,不加区分全导致出现莫名其妙的问题,本文我们来简单讨论下这些误差的种类,并尝试做出针对性的处理。需要说明的是,我们是为了工程上的合理,项目中的无 bug,效果的相对一致,并不刻意追求数学原理上的完美和精确。

二进制与浮点数

按照国际标准 IEEE 754,任意一个二进制浮点数可以表示成:符号位 + 指数位 + 尾数位。以 Float 类型为例,32 位浮点型,最高一位是符号位s,接着的8位是指数位E,最后的23位是有效数字M。
S01E23:计算几何中的误差来源分析

那么误差发生在哪里?一是 10 进制与 2 进制转换,会有不等价问题;二是有效数字长度有限,指数长度有限,带来的精度丢弃或溢出问题。

如何处理

对于这些涉及数学原理和计算机原理的问题,本系列文章统一不做处理!!!是的,拿来直接用,不做处理。

还有一个问题,浮点数还会分规格化和非规格化(Normal or Subnormal),本系列中统一按规格化处理,即最小值Float.leastNormalMagnitude,而不是Float.leastNonzeroMagnitude

运算过程

运算过程带来的问题大概有两种:

  • 计算结果溢出:比如计算过程中用到平方,就可能会太大或太小导致溢出;
  • 正逆运算无法抵消:比如乘以 3 再除以3,cos 运算再 acos 运算,理论上应该回到初始值,但是最后结果不一致。

如何处理

针对这些问题,也没有完美的策略,一般来说我们可以调整代码,采用提前计算或延迟计算某些值,优先避免溢出,再考虑精度问题。

比如,我们要计算 10 万个点的平均值,当然是先将它们加起来,再除以总数量,计算又快精度也高。但是这样在求和的过程中,就有溢出的风险,所以可以将每个点先除以总数量,再把这些微小值加起来得到平均值。但这样显然速度慢一些,精度也差一些。

而延迟计算的本质,其实是将问题统一丢给编译器,期待现代编译器的强大优化能力,能够帮助我们简化运算,并提高精度。比如先乘以 3 再除以 3,这样的表达式会被编译器直接优化掉。

近似算法与性能优化

在 3D 和 AR 中,为了提高效率,是有很多近似算法和性能优化算法的,它们也会带来误差。一般来说,我们可以认为:系统自带和知名第三方框架中的函数和运算都是可靠的,除非是极小或极大的特殊情况,否则无需处理。

另一种是,则是我们自己的近似算法,比如在计算向量长度时,用长度的平方来代替长度,比较角度大小时用 cosA 来代替 A 进行比较。

如何处理

如果是系统框架或知名第三方的,一般不用处理,绝大部分情况下是够用了。

而自己的替代算法也需要自行处理。比如使用向量长度平方来比较大小,也比较好处理:原来是计算 ||ab|| > 100,现在应该是 ||ab|| * ||ab|| > 100 * 100。

而三角函数其实是需要特殊处理的,如果只是简单比较夹角的大小(0~180):a > b,那么改为 cos(a) < cos(b) 并没有太多问题。

但是当我们在判断是否接近垂直或平行时,就可能会有问题:比如当 x 接近 90 度时,判断 cos(x) 绝对值小于 0.01 精度高,而判断 sin(x) 大于 0.99 则精度差。这是为什么呢?要从函数图像说起,严格地说是图像的斜率(即导数):
S01E23:计算几何中的误差来源分析
不管是 sin(x) 还是 cos(x),它们的规律是:斜率在 y = 0 点变化最大,在 y = ±1 时,斜率最小。这意味着:以弧度制计算,当 x 接近 90 度时,x 每变化 0. 01,cos(x) 值也会变化 -0.01;而 sin(x) 值变化 ±0.00005,几乎相当于不变。

这就是为什么,我们在判断向量是否垂直时,会使用 cos(x) (点乘)来判断;而判断向量是否平行时,则会使用 sin(x) (叉乘)来判断;

几何数据的物理意义

一般来说,3D 和 AR 中,我们并不是太在乎误差的存在,我们只希望它相对稳定且统一就行。

尤其是在 AR 中,和真实世界相关联,当两个点距离 0.0001 时,即 0.1 毫米时,就几乎看不出区别了,除非你离的特别近或者放大去看细节。所以距离和长度,需要考虑观察者的距离(最终显示出来的大小)。

说明

从开篇时,我们就遇到过计算精度问题,在前面的代码中,当我们遇到需要判断点是否重合,向量是否平行/垂直,向量是否是零(长度过短),都是笼统地用小于 0.0001 或者 Swift 提供的 Float 类型最小值Float.leastNormalMagnitude来简单判断。

事实上,这些是不合理的,不加区分全导致出现莫名其妙的问题,本文我们来简单讨论下这些误差的种类,并尝试做出针对性的处理。需要说明的是,我们是为了工程上的合理,项目中的无 bug,效果的相对一致,并不刻意追求数学原理上的完美和精确。

二进制与浮点数

按照国际标准 IEEE 754,任意一个二进制浮点数可以表示成:符号位 + 指数位 + 尾数位。以 Float 类型为例,32 位浮点型,最高一位是符号位s,接着的8位是指数位E,最后的23位是有效数字M。
S01E23:计算几何中的误差来源分析

那么误差发生在哪里?一是 10 进制与 2 进制转换,会有不等价问题;二是有效数字长度有限,指数长度有限,带来的精度丢弃或溢出问题。

如何处理

对于这些涉及数学原理和计算机原理的问题,本系列文章统一不做处理!!!是的,拿来直接用,不做处理。

还有一个问题,浮点数还会分规格化和非规格化(Normal or Subnormal),本系列中统一按规格化处理,即最小值Float.leastNormalMagnitude,而不是Float.leastNonzeroMagnitude

运算过程

运算过程带来的问题大概有两种:

  • 计算结果溢出:比如计算过程中用到平方,就可能会太大或太小导致溢出;
  • 正逆运算无法抵消:比如乘以 3 再除以3,cos 运算再 acos 运算,理论上应该回到初始值,但是最后结果不一致。

如何处理

针对这些问题,也没有完美的策略,一般来说我们可以调整代码,采用提前计算或延迟计算某些值,优先避免溢出,再考虑精度问题。

比如,我们要计算 10 万个点的平均值,当然是先将它们加起来,再除以总数量,计算又快精度也高。但是这样在求和的过程中,就有溢出的风险,所以可以将每个点先除以总数量,再把这些微小值加起来得到平均值。但这样显然速度慢一些,精度也差一些。

而延迟计算的本质,其实是将问题统一丢给编译器,期待现代编译器的强大优化能力,能够帮助我们简化运算,并提高精度。比如先乘以 3 再除以 3,这样的表达式会被编译器直接优化掉。

近似算法与性能优化

在 3D 和 AR 中,为了提高效率,是有很多近似算法和性能优化算法的,它们也会带来误差。一般来说,我们可以认为:系统自带和知名第三方框架中的函数和运算都是可靠的,除非是极小或极大的特殊情况,否则无需处理。

另一种是,则是我们自己的近似算法,比如在计算向量长度时,用长度的平方来代替长度,比较角度大小时用 cosA 来代替 A 进行比较。

如何处理

如果是系统框架或知名第三方的,一般不用处理,绝大部分情况下是够用了。

而自己的替代算法也需要自行处理。比如使用向量长度平方来比较大小,也比较好处理:原来是计算 ||ab|| > 100,现在应该是 ||ab|| * ||ab|| > 100 * 100。

而三角函数其实是需要特殊处理的,如果只是简单比较夹角的大小(0~180):a > b,那么改为 cos(a) < cos(b) 并没有太多问题。

但是当我们在判断是否接近垂直或平行时,就可能会有问题:比如当 x 接近 90 度时,判断 cos(x) 绝对值小于 0.01 精度高,而判断 sin(x) 大于 0.99 则精度差。这是为什么呢?要从函数图像说起,严格地说是图像的斜率(即导数):
S01E23:计算几何中的误差来源分析
不管是 sin(x) 还是 cos(x),它们的规律是:斜率在 y = 0 点变化最大,在 y = ±1 时,斜率最小。这意味着:以弧度制计算,当 x 接近 90 度时,x 每变化 0. 01,cos(x) 值也会变化 -0.01;而 sin(x) 值变化 ±0.00005,几乎相当于不变。

这就是为什么,我们在判断向量是否垂直时,会使用 cos(x) (点乘)来判断;而判断向量是否平行时,则会使用 sin(x) (叉乘)来判断;

几何数据的物理意义

一般来说,3D 和 AR 中,我们并不是太在乎误差的存在,我们只希望它相对稳定且统一就行。

尤其是在 AR 中,和真实世界相关联,当两个点距离 0.0001 时,即 0.1 毫米时,就几乎看不出区别了,除非你离的特别近或者放大去看细节。所以距离和长度,需要考虑观察者的距离(最终显示出来的大小)。

说明

从开篇时,我们就遇到过计算精度问题,在前面的代码中,当我们遇到需要判断点是否重合,向量是否平行/垂直,向量是否是零(长度过短),都是笼统地用小于 0.0001 或者 Swift 提供的 Float 类型最小值Float.leastNormalMagnitude来简单判断。

事实上,这些是不合理的,不加区分全导致出现莫名其妙的问题,本文我们来简单讨论下这些误差的种类,并尝试做出针对性的处理。需要说明的是,我们是为了工程上的合理,项目中的无 bug,效果的相对一致,并不刻意追求数学原理上的完美和精确。

二进制与浮点数

按照国际标准 IEEE 754,任意一个二进制浮点数可以表示成:符号位 + 指数位 + 尾数位。以 Float 类型为例,32 位浮点型,最高一位是符号位s,接着的8位是指数位E,最后的23位是有效数字M。
S01E23:计算几何中的误差来源分析

那么误差发生在哪里?一是 10 进制与 2 进制转换,会有不等价问题;二是有效数字长度有限,指数长度有限,带来的精度丢弃或溢出问题。

如何处理

对于这些涉及数学原理和计算机原理的问题,本系列文章统一不做处理!!!是的,拿来直接用,不做处理。

还有一个问题,浮点数还会分规格化和非规格化(Normal or Subnormal),本系列中统一按规格化处理,即最小值Float.leastNormalMagnitude,而不是Float.leastNonzeroMagnitude

运算过程

运算过程带来的问题大概有两种:

  • 计算结果溢出:比如计算过程中用到平方,就可能会太大或太小导致溢出;
  • 正逆运算无法抵消:比如乘以 3 再除以3,cos 运算再 acos 运算,理论上应该回到初始值,但是最后结果不一致。

如何处理

针对这些问题,也没有完美的策略,一般来说我们可以调整代码,采用提前计算或延迟计算某些值,优先避免溢出,再考虑精度问题。

比如,我们要计算 10 万个点的平均值,当然是先将它们加起来,再除以总数量,计算又快精度也高。但是这样在求和的过程中,就有溢出的风险,所以可以将每个点先除以总数量,再把这些微小值加起来得到平均值。但这样显然速度慢一些,精度也差一些。

而延迟计算的本质,其实是将问题统一丢给编译器,期待现代编译器的强大优化能力,能够帮助我们简化运算,并提高精度。比如先乘以 3 再除以 3,这样的表达式会被编译器直接优化掉。

近似算法与性能优化

在 3D 和 AR 中,为了提高效率,是有很多近似算法和性能优化算法的,它们也会带来误差。一般来说,我们可以认为:系统自带和知名第三方框架中的函数和运算都是可靠的,除非是极小或极大的特殊情况,否则无需处理。

另一种是,则是我们自己的近似算法,比如在计算向量长度时,用长度的平方来代替长度,比较角度大小时用 cosA 来代替 A 进行比较。

如何处理

如果是系统框架或知名第三方的,一般不用处理,绝大部分情况下是够用了。

而自己的替代算法也需要自行处理。比如使用向量长度平方来比较大小,也比较好处理:原来是计算 ||ab|| > 100,现在应该是 ||ab|| * ||ab|| > 100 * 100。

而三角函数其实是需要特殊处理的,如果只是简单比较夹角的大小(0~180):a > b,那么改为 cos(a) < cos(b) 并没有太多问题。

但是当我们在判断是否接近垂直或平行时,就可能会有问题:比如当 x 接近 90 度时,判断 cos(x) 绝对值小于 0.01 精度高,而判断 sin(x) 大于 0.99 则精度差。这是为什么呢?要从函数图像说起,严格地说是图像的斜率(即导数):
S01E23:计算几何中的误差来源分析
不管是 sin(x) 还是 cos(x),它们的规律是:斜率在 y = 0 点变化最大,在 y = ±1 时,斜率最小。这意味着:以弧度制计算,当 x 接近 90 度时,x 每变化 0. 01,cos(x) 值也会变化 -0.01;而 sin(x) 值变化 ±0.00005,几乎相当于不变。

这就是为什么,我们在判断向量是否垂直时,会使用 cos(x) (点乘)来判断;而判断向量是否平行时,则会使用 sin(x) (叉乘)来判断;

几何数据的物理意义

一般来说,3D 和 AR 中,我们并不是太在乎误差的存在,我们只希望它相对稳定且统一就行。

尤其是在 AR 中,和真实世界相关联,当两个点距离 0.0001 时,即 0.1 毫米时,就几乎看不出区别了,除非你离的特别近或者放大去看细节。所以距离和长度,需要考虑观察者的距离(最终显示出来的大小)。

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » S01E23:计算几何中的误差来源分析求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们