gpt4 book ai didi

javascript - Math.sin() .cos() 的成本 vs 怪异的自己的实现

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

所以大约一个小时前,我遇到了一个美好而尴尬的时刻,在很长一段时间后点击了一些东西。推到 30,我终于得到了 sinus 和 cosinus。在只能描述为基本上重新实现轮子的情节之后。


为了让 WASD 控件在两个轴上移动,同时考虑到玩家注视的方向,我决定使用一个简单的开关:

switch (key) {
case 'up':
movement.z -= 1 * modulation.z;
movement.x += 1 * modulation.x;
break;
case 'down':
movement.z += 1 * modulation.z;
movement.x -= 1 * modulation.x;
break;
case 'left':
movement.x -= 1 * modulation.z;
movement.z -= 1 * modulation.x;
break;
case 'right':
movement.x += 1 * modulation.z;
movement.z += 1 * modulation.x;
break;

...
}

... 其中 modulation.z 和 .x 将基于玩家面对的方向。调制值需要介于 -1 到 +1 之间。 (这应该是我的第一个线索,是的!)所以我帮自己拿了一些可靠的笔和纸,并且在对我 9 年级教育的幸福无知中我想到了:

function setModulation(rotation) {
var rotationTemp = 0;
var modulation = {};

rotationTemp = rotation;
if (rotationTemp > 180) {
rotationTemp = 360 - rotationTemp;
}
rotationTemp /= 180;

modulation.z = 1 - rotationTemp * 2;

rotationTemp = rotation + 90;
if (rotationTemp > 180) {
rotationTemp = 360 - rotationTemp;
}
rotationTemp /= 180;

modulation.x = 1 - rotationTemp * 2;
modulation.x *= -1;

return modulation;
};

在此期间学习和/或记住了一点,在重新访问这段代码时,我突然意识到:这是 cos 和 sin 的工作。老大。

function setModulationMath(rotation) {
var modulation = {};

modulation.z = Math.cos(rotation * Math.PI / 180);
modulation.x = Math.sin(rotation * Math.PI / 180);

return modulation;
};

到目前为止很开心!使用数学数学是为了什么!但后来我检查了性能。而我自己的“实现”在 FF、Chrome 和 IE 中要快得多。使用 1.000.000 次迭代,它在我的本地设置上增加了 35% 到 45% 之间。

有人知道为什么吗?它只是 Math.cos()/.sin() 吗?可衡量的增长远远超出人们的预期,不是吗?有经验的人愿意分享她*他的见解吗?

function setModulationMath(rotation) {
var modulation = {};

modulation.z = Math.cos(rotation * Math.PI / 180);
modulation.x = Math.sin(rotation * Math.PI / 180);

return modulation;
};

function setModulation(rotation) {
var rotationTemp = 0;
var modulation = {};

rotationTemp = rotation;
if (rotationTemp > 180) {
rotationTemp = 360 - rotationTemp;
}
rotationTemp /= 180;

modulation.z = 1 - rotationTemp * 2;

rotationTemp = rotation + 90;
if (rotationTemp > 180) {
rotationTemp = 360 - rotationTemp;
}
rotationTemp /= 180;

modulation.x = 1 - rotationTemp * 2;
modulation.x *= -1;

return modulation;
};

var iterations = 1000000;
console.time('setModulation');
for(var i = 0; i < iterations; i++ ){
setModulation(i, i / 2);
};
console.timeEnd('setModulation')

console.time('setModulationMath');
for(var i = 0; i < iterations; i++ ){
setModulationMath(i, i / 2);
};
console.timeEnd('setModulationMath')

最佳答案

您的功能可能会更快。然而,这种比较没有任何意义,因为这些函数会产生完全不同的结果。让我们以错误为基准:

var err_z = 0;
var err_x = 0;
for (var i = 0; i < 360; ++i){
var mm = setModulationMath(i);
var m = setModulation(i);
err_z += Math.abs(mm.z - m.z);
err_x += Math.abs(mm.x - m.x);
}

还有……

err_z == 49.17730025861921
err_x == 113.58865012930961

太糟糕了。如果两者完全相似,您会期望值接近 0。

While my first assumption was that I must have somehow faked my way through it: it perfectly works. Both functions give the same modulation values. This being said: I'd be happy to be told that this is a hack that only works because [x]... :)

平均误差在 z 轴上为 0.137,在 x 轴上为 0.316。这对您来说可能已经足够好了,但肯定存在差异更高的值。您可能只检查正交方向吗?在这种情况下,您需要的是一个开关,而不是三 Angular 函数。

编辑:哦,这是 z 部分的图表。波浪线是余弦,直线是您的近似值。

graphs

但我离题了。

(尝试)自己实现三 Angular 函数、数学函数等不一定是坏事。这实际上取决于应用程序的具体情况,有时您会发现不需要这样的精度,或者您的 Angular 将仅表示为整数度数……在这些情况下,使用更简单的近似值或查找表可能会有所帮助。

事实上,Javascript(以及许多其他标准库)中的正弦和余弦经过了很好的优化并且非常精确。

关于javascript - Math.sin() .cos() 的成本 vs 怪异的自己的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37787302/

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