来自this文章。这是代码:
float InvSqrt(float x){ // line 0
float xhalf = 0.5f * x;
int i = *(int*)&x; // store floating-point bits in integer
i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method
x = *(float*)&i; // convert new bits into float
x = x*(1.5f - xhalf*x*x); // One round of Newton's method
return x;
}
......我甚至不知道那是C还是C ++。 [好吧显然它是C,谢谢]有人可以为我翻译成Java吗?它(只是,我希望)第2和第4行令我感到困惑。
答案 0 :(得分:10)
您想使用以下方法:
strictfp
等可能存在问题。
大致是这样的:(注意:这是未经测试的!)
float InvSqrt(float x){ // line 0
float xhalf = 0.5f * x;
int i = Float.floatToIntBits(x); // store floating-point bits in integer
i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method
x = Float.intBitsToFloat(i); // convert new bits into float
x = x*(1.5f - xhalf*x*x); // One round of Newton's method
return x;
}
答案 1 :(得分:7)
这些行用于在float
和int
之间转换为位模式。 Java在java.lang.Float
中有静态方法 - 其他一切都是相同的。
static float InvSqrt(float x) { // line 0
float xhalf = 0.5f * x;
int i = Float.floatToIntBits(x); // store floating-point bits in integer
i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method
x = Float.intBitsToFloat(i); // convert new bits into float
x = x * (1.5f - xhalf * x * x); // One round of Newton's method
return x;
}
答案 2 :(得分:2)
你引用的代码是C,尽管注释是C ++风格的。
代码正在做什么涉及在位级别存储浮点值的方式。 “幻数”0x5f3759d5
与特定值有关。
初始化x
时访问浮点i
值的位,因为x
的地址被解除引用。因此,i
加载了浮点值的前32位。在下一行,使用x
的内容编写i
,更新工作近似值。
我已经读过这个代码在John Carmack用Id的开源Quake引擎发布它时变得很流行。代码的目的是快速计算1 / Sqrt(x),用于图形引擎的照明计算。
我无法将此代码直接转换为Java,因为它使用了如上所述的“类型双关语” - 当它访问内存中的float时就好像它是一个int。 Java阻止了这种活动,但正如其他人所指出的那样,Float对象提供了围绕它的方法。
在C中使用这个奇怪的实现的目的是为了它非常快。在编写本文时,我想这个方法有了很大的改进。我想知道今天的差异是否值得,当浮点运算变得更快时。
使用Java方法将float转换为整数位并返回可能比直接使用Java数学函数直接计算平方根而言要慢一些。
答案 3 :(得分:1)
好的,我现在出去了,因为我知道C,但我不懂Java。
用Java直接重写这个C代码是在乞求麻烦。 即使在C语言中,代码也是不可移植的。 除其他外,它依赖于: 浮点数的大小。 整数的大小。 浮点数的内部表示。 浮点数和整数的字节对齐方式。 使用逻辑右移实现右移(即i> 1) 算术右移(相对于算术右移) 具有高阶1位的整数因此不再等于除 2)。
我理解Java编译为字节码而不是直接编译 机器代码。字节码解释器的实现者使用调优 假设基于字节码的规范和理解 编译器从合理输入源输出的内容 码。
像这样的黑客不属于“明智的输入源”。
没有理由期望口译员会表现出来 你的C hack更快,实际上有很好的机会 它会慢一些。
我的建议是:IGNORE C代码。
寻找以Java为中心的效率提升。
C hack的概念是:
通过利用内部知识获得大约1 /平方(x) 浮点数的表示已经有了 指数被打破了数字,指数(x)/ 2更快 如果你已经有指数(x),则计算比root(x)。
然后hack执行牛顿方法的一次迭代 减少近似误差。我相信 一次迭代将错误减少到可容忍的程度。
也许这个概念值得在Java中进行调查, 但细节将取决于对亲密的了解 如何实现JAVA,而不是C的实现方式。
答案 4 :(得分:0)
你关心的线条非常简单。第2行采用float x
中的字节,这些字节位于某些浮点表示形式,如IEEE754,并将它们存储为整数,与它们完全相同。这将导致完全不同的数字,因为整数和浮点数以字节形式表示不同。第4行相反,并将该int中的字节再次传递给float