这只是为了满足我自己的好奇心。
是否实现了这一目标:
float InvSqrt (float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x;
i = 0x5f3759df - (i>>1);
x = *(float*)&i;
x = x*(1.5f - xhalf*x*x);
return x;
}在C#?如果它存在,发布代码。
我想我应该说我在寻找一个“安全”的实现.不管怎样,BitConverter代码解决了这个问题。工会的想法很有趣。我会测试并发布我的结果。
编辑:正如预期的那样,不安全的方法是最快的,其次是使用一个联合(函数内部),其次是BitConverter。这些函数被执行了10000000次,I使用System.Diagnostics.Stopwatch类来计时。计算结果显示在括号内。
Input: 79.67
BitConverter Method: 00:00:01.2809018 (0.1120187)
Union Method: 00:00:00.6838758 (0.1120187)
Unsafe Method: 00:00:00.3376401 (0.1120187)为了完整起见,我测试了内置的Math.Pow方法和“朴素”方法(1/Sqrt(x))。
Math.Pow(x, -0.5): 00:00:01.7133228 (0.112034710535584)
1 / Math.Sqrt(x): 00:00:00.3757084 (0.1120347)1/ Math.Sqrt()之间的差别非常小,因此我认为不需要求助于C#中的不安全快速InvSqrt()方法(或任何其他不安全的方法)。除非有人真的需要挤出CPU的最后一点汁液.1/Math.Sqrt()也更准确。
发布于 2008-11-06 14:40:59
您应该能够使用StructLayout和FieldOffset属性来伪造一个普通旧数据的联合,比如floats和ints。
[StructLayout(LayoutKind.Explicit, Size=4)]
private struct IntFloat {
[FieldOffset(0)]
public float floatValue;
[FieldOffset(0)]
public int intValue;
// redundant assignment to avoid any complaints about uninitialized members
IntFloat(int x) {
floatValue = 0;
intValue = x;
}
IntFloat(float x) {
intValue = 0;
floatValue = x;
}
public static explicit operator float (IntFloat x) {
return x.floatValue;
}
public static explicit operator int (IntFloat x) {
return x.intValue;
}
public static explicit operator IntFloat (int i) {
return new IntFloat(i);
}
public static explicit operator IntFloat (float f) {
return new IntFloat(f);
}
}那么翻译InvSqrt就很容易了。
发布于 2008-11-06 14:39:46
如果要避免不安全的代码,请使用BitConverter。
float InvSqrt(float x)
{
float xhalf = 0.5f * x;
int i = BitConverter.SingleToInt32Bits(x);
i = 0x5f3759df - (i >> 1);
x = BitConverter.Int32BitsToSingle(i);
x = x * (1.5f - xhalf * x * x);
return x;
}上面的代码使用了.NET Core2.0中引入的新方法。对于.NET框架,必须返回以下内容(执行分配):
float InvSqrt(float x)
{
float xhalf = 0.5f * x;
int i = BitConverter.ToInt32(BitConverter.GetBytes(x), 0);
i = 0x5f3759df - (i >> 1);
x = BitConverter.ToSingle(BitConverter.GetBytes(i), 0);
x = x * (1.5f - xhalf * x * x);
return x;
}否则,C#代码与您提供的C代码完全相同,只需将该方法标记为不安全:
unsafe float InvSqrt(float x) { ... }发布于 2008-11-06 14:45:55
绝对有可能在不安全的情况下。请注意,尽管在地震3源代码中使用了常数0x5f3759df,但数值研究表明表示,对于牛顿近似,常数0x5f375a86实际上得到了更好的结果。
https://stackoverflow.com/questions/268853
复制相似问题