gpt4 book ai didi

c++ - 3D vector 归一化问题

转载 作者:行者123 更新时间:2023-11-28 00:30:02 24 4
gpt4 key购买 nike

我发现 3D Vector 规范化存在问题。似乎它只发生在一些特定的数字上。每次调用规范化函数时,Vector 都会发生变化。

示例代码:

Vector3 v1(-0.965090453265, -0.210381150246, 0.156014174223);

std::cout.precision(15);
v1.normalize();
std::cout << v1 << std::endl;
v1.normalize();
std::cout << v1 << std::endl;
v1.normalize();
std::cout << v1 << std::endl;
v1.normalize();
std::cout << v1 << std::endl;

输出:

-0.965090334415436 -0.210381120443344 0.156014159321785
-0.965090453624725 -0.210381150245667 0.156014174222946
-0.965090334415436 -0.210381120443344 0.156014159321785
-0.965090453624725 -0.210381150245667 0.156014174222946

归一化函数:

void Vector3::normalize()
{
if ( length() == 0 )
return;

Vector3 x = *this;
float sqr = x.x * x.x + x.y * x.y + x.z * x.z;
*this = x * (1.0f / std::sqrt(sqr));
}

这是 float 精度的问题,还是我的代码有问题?如何避免这个问题?

最佳答案

编辑:刚刚弄清楚为什么我无法重现问题。

如果我将下面代码中的 x /= len 更改为 x *= ((t) 1.) / len 那么我最终得到的正是您为 floats 提供的内容,即前六位数字之外的不一致答案(无论如何您都不应该相信 float):

-0.965090334415436 -0.210381120443344 0.156014159321785
-0.965090453624725 -0.210381150245667 0.156014174222946
-0.965090334415436 -0.210381120443344 0.156014159321785
-0.965090453624725 -0.210381150245667 0.156014174222946
-0.965090334415436 -0.210381120443344 0.156014159321785

正如预期的那样,doubles 直到第 15 位数字仍然正确:

-0.965090340387771 -0.210381125639766 0.156014155975542
-0.965090340387771 -0.210381125639766 0.156014155975542
-0.965090340387771 -0.210381125639766 0.156014155975542
-0.965090340387771 -0.210381125639766 0.156014155975542
-0.965090340387771 -0.210381125639766 0.156014155975542

不过,float 结果始终与前六位一致。

原帖:

这似乎是“只是一个浮点精度问题”,因为单精度 float 最多只能提供 6-9 decimal digits of precision 。我已经编写了代码来检查这个,我的结果似乎没有你的那么糟糕。

#include <iostream>
#include <cmath>

template <typename t>
class Vector3
{

public:
t x;
t y;
t z;

Vector3 (t x, t y, t z) :
x (x),
y (y),
z (z)
{}

void normalize()
{
t len = std::sqrt(x * x + y * y + z * z);

if (len != 0.)
{
x /= len;
y /= len;
z /= len;
}
}

void println()
{
std::cout << x << " " << y << " " << z << std::endl;
}

};

int main(int argc, char ** argv)
{
std::cout.precision(15);

Vector3<float> v(-0.965090453265, -0.210381150246, 0.156014174223);

for (int i = 0; i < 5; ++i)
{
v.normalize();
v.println();
}

return 0;

}

输出:

-0.965090334415436 -0.210381120443344 0.156014159321785
-0.965090394020081 -0.210381135344505 0.156014174222946
-0.965090394020081 -0.210381135344505 0.156014174222946
-0.965090394020081 -0.210381135344505 0.156014174222946
-0.965090394020081 -0.210381135344505 0.156014174222946

Vector3<float> 更改为 Vector3<double> 会给出直到第 15 位的一致结果:

-0.965090340387771 -0.210381125639766 0.156014155975542
-0.965090340387771 -0.210381125639766 0.156014155975542
-0.965090340387771 -0.210381125639766 0.156014155975542
-0.965090340387771 -0.210381125639766 0.156014155975542
-0.965090340387771 -0.210381125639766 0.156014155975542

请注意,即使 float 结果停止变化,前七位以外的数字实际上并不正确。

关于c++ - 3D vector 归一化问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23303598/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com