“ System.Math.Cos”是否可以返回(浮点数)?

问题描述 投票:14回答:5

在C#中,使我烦恼的是,没有“ Math.Cos”函数会返回浮点数。双精度值是您可以获取的唯一值,从而迫使您将其强制转换为浮点型。像这样:float val = (float)Math.Cos(someVal);

我需要使用浮点数,因为我正在严格使用浮点数的Direct3D中进行操作。浮点数是32位元,在图形世界(按现在的状态)更为常见。

我可以使用的C#中是否有任何功能可以像C ++一样处理浮点数?

我不想包装任何C ++东西,因为它需要在XNA和Linux for OpenGL上运行。

NOTE:如果代码没有将双精度浮点数转换为浮点数,将非常好。

c# .net math floating-point double
5个回答
6
投票

如果不进行深入的数学讨论,您将无法编写自己的accurate Cos函数。这是使用扩展方法的建议:

class Program
{
    static void Main(string[] args)
    {
        float cos = Math.Cos(.25d).ToFloat();

        Console.WriteLine("cos(.25d) = {0}", cos);

        Console.ReadKey();
    }
}

public static class MathExtensions
{
    public static float ToFloat(this double value)
    {
        return (float)value;
    }
}

这是使用Func<T, TResult>并创建自己的MathF静态类的另一种方式:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("cos(.25d) = {0}", MathF.Cos(.25d));
        Console.WriteLine("sin(.25d) = {0}", MathF.Sin(.25d));

        Console.ReadKey();
    }
}

public static class MathF
{
    public static Func<double, float> Cos = angleR => (float)Math.Cos(angleR);
    public static Func<double, float> Sin = angleR => (float)Math.Sin(angleR);
}

正如其他人指出的那样,正如zezba在他的测试代码中确认的那样,Func委托的执行速度会变慢(我不知道委托会慢得多)。最快的是直接漂浮。中间问题是MathF静态类中的简单静态方法调用。


5
投票

好,所以我运行了一些基准测试,以查看阅读“ dboarman”回复后最快的方法。遗憾的是,如果不使用严格的c#进行强制转换,就无法做到这一点,最快的方法是现场进行强制转换,因此,因为我很关心速度,因为它主要是用于游戏,因此不宜使用旧的强制转换方法。

这些测试是使用以下规范进行编译的::

C# .NET 4.0
ConsoleApplication - Release - Optimized code - x64
4gb ram, 2.4ghz AMD_X2_DualCore 4600 CPU, running Windows7 Ultimate.

代码:

static void Main(string[] args)
{
    //Start
    Console.Write("Hit Enter to Start\n");
    Console.ReadLine();
    long num = 100;
    long mil = 0;
    float val = 0.01f;
    Stopwatch startTime = new Stopwatch();

    //Run
    for(long i = 0; i != num; ++i)
    {
        startTime.Restart();
        for(uint i2 = 0; i2 != 1000000; ++i2) val = (float)System.Math.Cos(val);// 48 Milliseconds
        //for(uint i2 = 0; i2 != 1000000; ++i2) val = System.Math.Cos(val).ToFloat();// 53 Milliseconds
        //for(uint i2 = 0; i2 != 1000000; ++i2) val = MathF2.Cos(val);// 59 Milliseconds
        //for(uint i2 = 0; i2 != 1000000; ++i2) val = MathF.Cos(val);// 63 Milliseconds
        startTime.Stop();
        mil += startTime.ElapsedMilliseconds;
    }

    //End
    mil /= num;

    //Print
    Console.Write("Milliseconds = "+mil.ToString());
    Console.ReadLine();
}

这是测试的基本数学代码::

public static class MathF
{
    public static Func<double, float> Cos = angleR => (float)System.Math.Cos(angleR);
    public static Func<double, float> Sin = angleR => (float)System.Math.Sin(angleR);
}

public static class MathF2
{
    public static float Cos(float pValue) {return (float)System.Math.Cos(pValue);}
}

public static class MathExtensions
{
    public static float ToFloat(this double value)
    {
        return (float)value;
    }
}

4
投票

我将创建一个MathCommonMethods类,该类的方法会将所有常用的返回类型转换为double形式的浮点数。从长远来看,这将节省您键入的时间。

就现有的函数而言,它以浮点数返回值,我还没有听说过。

如果精度对您的应用很重要,则在铸造时也应注意不要丢失精度。


2
投票

如果要避免强制转换,则需要其他实现。如果您正在跨平台,则可以创建一个平台抽象层,在其中您可以基于平台放置不同的实现。这将有助于提高性能。如果性能不是问题(游戏就是这种情况),那么创建一个效用函数并执行强制转换是一个很好的解决方案。


2
投票

从.NET Core 2.0(.NET Standard 2.1)(C#8.0)及更高版本开始作为内置函数,这是可能的。

您可以仅将MathF类与内置常量或与float类型一起使用的函数一起使用。

示例:

float cos = MathF.Cos(MathF.PI);

有关更多信息,请参见documentation on MSDN有关MathF类型。

© www.soinside.com 2019 - 2024. All rights reserved.