“System.Math.Cos”可以返回一个(浮点数)吗?

时间:2010-12-03 21:35:22

标签: c# .net math floating-point double

在C#中,它告诉我如何没有返回浮点数的“Math.Cos”函数。 double是你可以获得的唯一值,因此强迫你将它转换为浮点数。 像这样:
float val = (float)Math.Cos(someVal);

我需要使用浮动因为我在Direct3D中做了严格使用浮点数的东西。 浮点数在图形世界中更常见(因为它现在是),因为它们是32位。

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

我不想包装任何C ++的东西,因为这需要在XNA& Linux for OpenGL。

注意:如果代码没有将double转换为浮点数,那就太棒了。

5 个答案:

答案 0 :(得分:6)

如果不进行深入的数学运算,您将无法编写自己的准确 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静态类中的简单静态方法调用。

答案 1 :(得分:6)

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

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

示例:

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

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

答案 2 :(得分:4)

我会创建一个MathCommonMethods类,其方法可以将所有常用的返回类型转换为leiu of double中的浮点数。从长远来看,这将为您节省一些打字。

只要存在一个将值作为float返回的现有函数,我就没有听说过。

如果精度对您的应用很重要,那么在施法时也应该小心,不要失去精确度。

答案 3 :(得分:4)

好的,所以我在阅读“dboarman”回复后运行了一些基准测试,看看哪种方法最快。可悲的是,如果没有使用严格的c#&amp; amp;最快的方法就是现场施法,所以因为我关心速度,因为它主要是因为游戏不符合旧的演员方法。

使用以下规范::

编译这些测试
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();
}

以下是tests ::

的基础数学代码
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 :(得分:2)

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