0

假设我正在写一vector2D库的rotate()方法的实现。存储三角函数调用的结果是否有意义?

vector2D rotate(const vector2D vector, const vector2D origin, float radians) 
{ 
    // Implementation details 
    return {x, y}; 
} 

我可以存储三角函数的结果调用的变量,所以我不必多次打电话给他们:

float sr = sin(radians); 
float cr = cos(radians); 
float x = origin.x + (
    (vector.x - origin.x) * cr - (vector.y - origin.y) * sr 
); 
float y = origin.y + (
    (vector.x - origin.x) * sr + (vector.y - origin.y) * cr 
); 

或者,我可以简单的写了我的意思

float x = origin.x + (
    (vector.x - origin.x) * cos(radians) - (vector.y - origin.y) * sin(radians) 
); 
float y = origin.y + (
    (vector.x - origin.x) * sin(radians) + (vector.y - origin.y) * cos(radians) 
); 
  • 这些情况的优缺点是什么?
  • 编译器是否优化了第二个示例中的开销?或者,即使在vector2D库的情况下,调用trig函数的开销多少也不明显?

回答

3

第一个版本可能是编译器在优化第二个版本时生成的代码。

某些编译器可能知道sincos是纯函数,它们始终为特定参数返回相同的值。但语言标准对此没有提及,所以我们不能确定。

此外,在尝试像这样的本地优化之前,您可能会问自己是否经常调用此函数以成为应用程序的瓶颈。如果不是,也许不会注意到确切的速度差异。

gcc编译器将sin和cos映射到__builtin_sin and __builtin_cos,所以它对这些函数有更多的了解,但我不知道优化器是否会利用这些功能。

+0

gcc编译器将sin和cos映射到['__builtin_sin'和'__builtin_cos'](https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html),因此它具有这些函数的其他知识,但我不知道优化器是否会利用这一点。 –

+1

GCC不仅可以保存sin/cos的结果,而且可以同时计算[两者同时](http://goo.gl/fkSLcf)。 Clang并不那么尖锐,可悲。另一件要考虑的事情是:如果你在双打中进行计算,则会产生更少的代码。 –

+0

@Revolver_Ocelot'双打计算'是什么意思? “双打”作为第二个例子中的重复代码? – sjaustirni

1

您也可以定义变量vector.x - origin.xvector.y - origin.y。如前所述,这并不是性能问题,因为编译器无论如何都会实现这些优化,而只是代码可读性问题。

如果您创建这些附加变量,则还应声明它们为const,因为您不打算更改它们的值。

有关于如何使用这些“冗余”变量不同的意见。我个人会使用它们,如果我能找到一个有意义的名字。

+0

非常好的评论,但不完全是问题的答案。您能否将其作为评论发布? – sjaustirni

+0

@Dundee:不确定,你一直在寻求优点和缺点,我认为我在现有答案中增加了一些其他方面。 –

+0

的确如此。我在使用trig函数时想要利弊,但没有说清楚。无论如何,我现在不会改变它,所以这应该留下来作为答案。 – sjaustirni