C# 模与环的极限旋转
在向遗留代码添加单元测试时,我发现了以下构造:C# 模与环的极限旋转,c#,optimization,rotation,C#,Optimization,Rotation,在向遗留代码添加单元测试时,我发现了以下构造: double rotationX = Math.Abs(newRotationX % 360 + 360) % 360; 它基本上强制旋转为范围[0360)内的值。负数变为正数(-1应变为359),大数受到限制(725应变为5) 循环会更有效吗 double rotationX = newRotation; while (rotationX < 0) rotationX += 360; while (rotationX &g
double rotationX = Math.Abs(newRotationX % 360 + 360) % 360;
它基本上强制旋转为范围[0360)
内的值。负数变为正数(-1
应变为359
),大数受到限制(725
应变为5
)
循环会更有效吗
double rotationX = newRotation;
while (rotationX < 0)
rotationX += 360;
while (rotationX >= 360)
rotationX -= 360;
这似乎是一个非常小的问题,编译器可能会尽最大努力对其进行优化 如果它真的能让你的船漂浮起来,你可以很快模拟一个测试和基准测试,但是要想使它有效,有很多事情需要记住,这可能是不值得的 此外: 过早优化是恶意帖子和文章的根源:
- 还有很多,所以
我想,对于遗留代码,您可能有更好的问题需要担心:)在我看来,
Math.Abs
调用是不必要的,因为负数的模将得到介于-359和0之间的值,然后再加上360,您将处于正范围内。最终的模360将为need留下来处理不需要添加360的正数。在执行此操作时,删除堆栈上的一个调用
var rotationX =
(newRotationX % 360 + 360) // puts any negative number into the positive range
% 360; // puts any positive numbers back into the 0-359 range
在第二个示例中,使用单模运算可能更为理想。但您确实需要分析代码,以确定哪个选项的性能最好。在这样的小范围内,效率绝对不是您应该考虑的问题。原始操作可能是最优的。您的第二个示例e将在非常大的负数上给出错误的结果。@Magus:虽然我同意早期优化通常是一件坏事,但我们发现这种方法每帧可以调用一次(大约每秒60次)当用户抓住旋转gizmo时。出于这个原因,我们正在尝试优化经常被调用的部分。是的,但简单的数学运算不可能比循环慢。处理器专门设计为每秒执行大量数学运算。如果您试图优化代码,最好先对其进行分析识别次优代码,而不是根据调用频率猜测。如果整圈是基数2的倍数,例如,2、4、8、16、32、64、…、512,则可以使用掩码运算符
&
。但遗憾的是,它是360,而不是256或512。但如果碰巧使用基数2旋转数字,则只能使用&
旋转数字不要使用模+加法+模。首先,将除数减去1,然后将其屏蔽为数字。例如,对于512旋转,使用511作为屏蔽器:-1&511==511;-2&511==510;-3&511=509;1&511==1;2&511==2;511&511==511;512&511==0;515&511==3
。这是一个小提琴示例:Math.Abs
i这是多余的,但是一个单数模和一个if
语句不是比一个加上另一个模的语句更有效吗?@OnlineCop正如我在回答中所说的,很可能是一个单模运算,然后一个if
,然后在负数时加上360可能更为理想。但是如果没有代码,看看是哪一个h选项性能更好,您只是在猜测。
var rotationX =
(newRotationX % 360 + 360) // puts any negative number into the positive range
% 360; // puts any positive numbers back into the 0-359 range