C# 如何计算C中浮点的平方根#
如何计算C# 如何计算C中浮点的平方根#,c#,math,square-root,C#,Math,Square Root,如何计算C#中Float的平方根,类似于XNA中的Core.Sqrt,计算它的double,然后返回到Float。可能有点慢,但应该可以 (float)Math.Sqrt(inputFloat) 我不想这么说,但0x5f3759df似乎需要3倍于Math.Sqrt的时间。我只是用定时器做了一些测试。 for循环中的Math.Sqrt访问预先计算的阵列,结果大约为80ms。 0x5f3759df在相同情况下导致180+毫秒 使用释放模式优化进行了多次测试 资料来源如下: /* =====
C#
中Float
的平方根,类似于XNA中的Core.Sqrt
,计算它的double
,然后返回到Float。可能有点慢,但应该可以
(float)Math.Sqrt(inputFloat)
我不想这么说,但0x5f3759df似乎需要3倍于Math.Sqrt的时间。我只是用定时器做了一些测试。 for循环中的Math.Sqrt访问预先计算的阵列,结果大约为80ms。 0x5f3759df在相同情况下导致180+毫秒 使用释放模式优化进行了多次测试 资料来源如下:
/*
================
SquareRootFloat
================
*/
unsafe static void SquareRootFloat(ref float number, out float result)
{
long i;
float x, y;
const float f = 1.5F;
x = number * 0.5F;
y = number;
i = *(long*)&y;
i = 0x5f3759df - (i >> 1);
y = *(float*)&i;
y = y * (f - (x * y * y));
y = y * (f - (x * y * y));
result = number * y;
}
/*
================
SquareRootFloat
================
*/
unsafe static float SquareRootFloat(float number)
{
long i;
float x, y;
const float f = 1.5F;
x = number * 0.5F;
y = number;
i = *(long*)&y;
i = 0x5f3759df - (i >> 1);
y = *(float*)&i;
y = y * (f - (x * y * y));
y = y * (f - (x * y * y));
return number * y;
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
int Cycles = 10000000;
Random rnd = new Random();
float[] Values = new float[Cycles];
for (int i = 0; i < Cycles; i++)
Values[i] = (float)(rnd.NextDouble() * 10000.0);
TimeSpan SqrtTime;
float[] Results = new float[Cycles];
DateTime Start = DateTime.Now;
for (int i = 0; i < Cycles; i++)
{
SquareRootFloat(ref Values[i], out Results[i]);
//Results[i] = (float)Math.Sqrt((float)Values[i]);
//Results[i] = SquareRootFloat(Values[i]);
}
DateTime End = DateTime.Now;
SqrtTime = End - Start;
Console.WriteLine("Sqrt was " + SqrtTime.TotalMilliseconds.ToString() + " long");
Console.ReadKey();
}
}
/*
================
方根浮子
================
*/
不安全的静态无效SquareRootFloat(参考浮点数,超出浮点数结果)
{
龙我;
浮动x,y;
常数浮点f=1.5F;
x=数量*0.5F;
y=数量;
i=*(长*)&y;
i=0x5f3759df-(i>>1);
y=*(浮动*)&i;
y=y*(f-(x*y*y));
y=y*(f-(x*y*y));
结果=数字*y;
}
/*
================
方根浮子
================
*/
不安全的静态浮点数SquareRootFloat(浮点数)
{
龙我;
浮动x,y;
常数浮点f=1.5F;
x=数量*0.5F;
y=数量;
i=*(长*)&y;
i=0x5f3759df-(i>>1);
y=*(浮动*)&i;
y=y*(f-(x*y*y));
y=y*(f-(x*y*y));
返回编号*y;
}
///
///应用程序的主要入口点。
///
[状态线程]
静态void Main()
{
整数周期=10000000;
随机rnd=新随机();
浮动[]值=新浮动[周期];
对于(int i=0;i
float和double计算方式不同否?@Chris-Math.Sqrt方法接受一个double并返回一个double。这就是为什么我将参数转换为double。我看到了。但我说的是浮子。无论如何,谢谢你,我一直希望.Net能以某种方式优化它,使其成为幕后的全浮点(全32位)操作。有人知道这是否得到了优化吗?@Chris,精度将与输入相同。计算是用double来完成的。@Chris:不,有一个众所周知的浮点分析定理可以保证得到正确的结果。因为double的精度比float高得多,所以损失很小或根本不存在。通过使用浮动,您已经说过您不太关心精度。@CodeInChaos:请注意,精度损失甚至不是“非常小”。假设转换和双精度平方根被正确舍入,这将为所有可能的输入提供一个正确舍入的单精度平方根。使用强大的魔法-魔法是平方根的逆。但sqrt也有类似的魔力。这就失去了精确性。@CodeInChaos-本文中的第二个代码示例有一个sqrt的实现:“请注意,唯一真正的区别是返回值–而不是返回y,返回numbery作为平方根”*是。jball发布的内容主要是出于一种冷静的好奇心,只有在性能比精度重要得多的情况下才有用。首先,我会使用简单的内置内容,只有在性能确实需要的情况下才会切换到复杂的解决方案,并且分析表明更改实际上很重要。@CodeInChaos是绝对正确的(因此我的“强大的魔法”声明,而不是将其作为答案发布)。始终为可读性、可维护性和准确性编写代码(例如,(float)Math.Sqrt(inputFloat)
),除非您有实际的性能问题。老实说,这看起来很离题,但无论如何都很有趣?欢迎来到堆栈溢出!虽然这个答案可能是正确和有用的,但如果你想解释一下它是如何帮助解决问题的,那就更好了。如果有一个变化(可能是无关的)导致它停止工作,并且用户需要了解它曾经是如何工作的,那么这在将来变得特别有用。
/*
================
SquareRootFloat
================
*/
unsafe static void SquareRootFloat(ref float number, out float result)
{
long i;
float x, y;
const float f = 1.5F;
x = number * 0.5F;
y = number;
i = *(long*)&y;
i = 0x5f3759df - (i >> 1);
y = *(float*)&i;
y = y * (f - (x * y * y));
y = y * (f - (x * y * y));
result = number * y;
}
/*
================
SquareRootFloat
================
*/
unsafe static float SquareRootFloat(float number)
{
long i;
float x, y;
const float f = 1.5F;
x = number * 0.5F;
y = number;
i = *(long*)&y;
i = 0x5f3759df - (i >> 1);
y = *(float*)&i;
y = y * (f - (x * y * y));
y = y * (f - (x * y * y));
return number * y;
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
int Cycles = 10000000;
Random rnd = new Random();
float[] Values = new float[Cycles];
for (int i = 0; i < Cycles; i++)
Values[i] = (float)(rnd.NextDouble() * 10000.0);
TimeSpan SqrtTime;
float[] Results = new float[Cycles];
DateTime Start = DateTime.Now;
for (int i = 0; i < Cycles; i++)
{
SquareRootFloat(ref Values[i], out Results[i]);
//Results[i] = (float)Math.Sqrt((float)Values[i]);
//Results[i] = SquareRootFloat(Values[i]);
}
DateTime End = DateTime.Now;
SqrtTime = End - Start;
Console.WriteLine("Sqrt was " + SqrtTime.TotalMilliseconds.ToString() + " long");
Console.ReadKey();
}
}
private double operand1;
private void squareRoot_Click(object sender, EventArgs e)
{
operand1 = Math.Sqrt(operand1);
this.textBox1.Text = operand1.ToString();
}