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();
}