【发布时间】:2023-03-06 10:01:01
【问题描述】:
我在 Christopher Ttremblay 的《游戏程序员数学》一书中找到了以下代码。它看起来像 c++,他确实对 stllib 的性能比较做了很多引用,给出的代码如下:
float Exp2(float X)
{
float Result, Square, IntPow;
if (X < 0) {
const unsigned long IntVal = *(unsigned long *)&X & 0x7FFFFFFF;
const unsigned long Int = (IntVal >> 23) - 127;
if ((long)Int > 0) {
*(unsigned long *)&IntPow = ((((IntVal & 0x007FFFFF) |
0x00800000) >> (23 - Int)) + 127 + 1) << 23;
*(unsigned long *)&X = (((IntVal << Int) & 0x007FFFFF)
| 0x3F800000);
X = 2.0f - X;
} else {
IntPow = 2.0f;
X++;
}
Result = X0CoEff + Square * X1CoEff;
Square *= X; // The 2 last lines are repeated for every coeff.
Result += Square * XiCoEff;
...
return Result / IntPow;
} else {
const unsigned long IntVal = *(unsigned long *)&X;
const unsigned long Int = (IntVal >> 23) - 127;
if ((long)Int > 0) {
*(unsigned long *)&IntPow = ((((IntVal & 0x007FFFFF) |
0x00800000) >> (23 - Int)) + 127) << 23;
*(unsigned long *)&X = (((IntVal << Int) & 0x007FFFFF)
| 0x3F800000);
X—;
} else
IntPow = 1.0f;
Square = X;
Result = X0CoEff + Square * X1CoEff;
Square *= X; // The 2 last lines are repeated for every coeff.
Result += Square * XiCoEff;
...
return Result * IntPow;
}
}
float log2(float X)
{
float Result, Square;
Result = (float)((*(unsigned long *)&X) >> 23) - 127 + x0CoEff;
*(unsigned long *)&X = (*(unsigned long *)&X & 0x007FFFFF) | 0x3F800000;
Square = X;
Result += Square * XiCoEff;
Square *= X; // The 2 last lines are repeated for every coeff.
...
return Result;
}
问题是我实际上从未学习过位操作(我认为这就是这里发生的事情,如果没有,我仍然从未在我的编码作业中处理过十六进制)。如果有人可以通过评论或将其翻译为更高级别的 c/c++ 以进行理解并可能提供帮助。
这本书解释说,与 stllib 相比,这些应该是函数的优化版本,但正如您所见,代码的注释不是很好(这些行是逐个字符复制的)
【问题讨论】:
-
什么意思?已经很高级了! :P
-
@scientiaesthete 好吧,也许高层是错误的术语,但我的意思更多的是不专门处理这些位,而是这些位所持有的值发生了什么。
-
这是一堆算术魔法。 Oleksi 所说的。
-
如果你不熟悉位操作,这不是学习的东西。如果您以前从未使用过钢材,这就像试图了解悬索桥的设计一样。在尝试跑马拉松之前,您需要爬行。
-
这个问题应该重新打开。位混洗的复杂性在这里无关紧要。随着处理器对这种黑客行为越来越敏感,这本书已经过时了。在 FP 和 int 寄存器之间移动很慢而且越来越慢,可能有指令可以加速这个操作。答案是在深入研究 IEEE 754 格式之前检查性能是否真的提高了。