c++ - 在执行点积之前对向量进行归一化?
问题描述
我有一个经典练习,要求我检查一个角色是否从背后受到攻击(背刺或射弹)。我知道我可以为此使用点积,我只是想知道我是否必须先对向量进行归一化,或者这无关紧要。
我的理由是,如果矢量坐标是巨大的数字,是否会导致我的点积溢出或下溢。
float dotProd(Vector3& P, Vector3& Q)
{
return P.x * Q.x + P.y * Q.y + P.z * Q.z;
}
bool sneakAttack(Vector3& proj, Vector3& player)
{
if(dotProd(proj, player) > 0)
return true;
else
return false;
}
解决方案
规范化可能会使您的代码更容易溢出。
假设向量P
有长度A
并且Q
有长度B
。为了规范化第一个向量,通常的方法是将每个坐标除以A
,这是通过首先计算 A 2获得的,它恰好等于P·P
。有问题。如果A >= B
,那么P·P >= |P·Q|
。因此,如果P·Q
溢出,则P·P
溢出。在溢出成为您的点积的问题之前,它已经成为规范化的问题。
还有另一个需要注意的危险,这可能是发现您需要处理的值范围的另一个原因。考虑以下情况
P.x = 1024
,P.y = 0.2
,P.z = 1024
,
Q.x = 1024
,Q.y = 0.2
, 和Q.z = -1024
.
在数学上,这种情况下的点积是P.y * Q.y
。但是(^
用于表示幂)您的点积计算为(2^20 + 0.04) - 2^20
。2^20
和的数量级差异0.04
对于 23 位尾数来说太大了。所以他们的总和计算为2^20
。减去2^20
没有任何迹象表明符号P.y * Q.y
是什么。标准化在这里没有帮助,因为它只会将问题转移到 2 的低次方。解决这个问题可能会解决溢出威胁作为副作用。
推荐阅读
- java - Maven 问题:项目没有父级
- sql - 试图在 SQL Server 中找到总和的中位数
- php - Codeigniter 3.1.11 - 登录会话变量未加密 php 7.2
- java - 雪花插入锁定表
- laravel - 仅在一条路线 Laravel 7 中未找到 404 错误
- python - 使用补丁自定义散点图中的图例标记面颜色
- highcharts - HighCharts:以样式模式导出带背景的 jpeg
- oracle-apex - 插入数据库日期和时间
- sql - 与数字数据类型进行日期比较时性能缓慢
- android - 保存 Android mediaRecorder 输出并将其上传到 Firebase 存储