Can “System.Math.Cos” return a (float)?

本秂侑毒 提交于 2020-05-23 08:00:24

问题


In C# it bugs me how there is no "Math.Cos" function that returns a float. A double is the only value you can get back thus forcing you to cast it to a float. Like so:
float val = (float)Math.Cos(someVal);

I need to use floats because i'm doing stuff in Direct3D which strictly uses floats. Floats are much more common in the graphics world(as it stands now) because they are 32bit.

Is there any functionality within C# I can use that would simply just process floats like C++ can do??

I do not want to wrap any C++ stuff because this needs to run on XNA & Linux for OpenGL.

NOTE: It would nice to have code that did not cast a double to a float.


回答1:


Without going into some in-depth math, you will not be able to write your own accurate Cos function. Here is a suggestion though using extension method:

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

This is another way using Func<T, TResult> and creating your own MathF static class:

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

As others have pointed out, the Func delegates will be slower as zezba confirmed in his test code (I didn't know that the delegates would be that much slower). The quickest is the direct cast to float. The middle ground would be simple static method calls in the MathF static class.




回答2:


Ok so I ran some benchmarks to see what method was the fastest after reading "dboarman" reply. Sadly it seams there is no way to do it without casting using strictly c# & the fastest method is to just cast on spot, so because I care about speed as its mostly for games ill be sticking with the old cast method.

These tests were compiled using the following specs::

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

Code:

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

Here is the base math code for the 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;
    }
}



回答3:


Starting with .NET Core 2.0 (.NET Standard 2.1) (C# 8.0) and upper this is possible thing as built-in function.

You can just use MathF class with built-in constants or functions working with float type.

Example:

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

For further information see documentation on MSDN about MathF type.




回答4:


I would create a MathCommonMethods class with methods that would convert all of the frequently used return types to floats in leiu of doubles. This will save you some typing in the long run.

As far as there being an existing function that returns the value as a float, I've not heard of one.

You should also be careful too when casting not to lose precision, if precision is important to your application.




回答5:


If you want to avoid casting, you'll need a different implementation. If you are doing cross-platform, you can create a platform abstraction layer where you can put different implementations based on the platform. This will help with performance. If perf isn't an issue (is this ever the case with games), then creating a utility function and performing the casting there is a good solution.



来源:https://stackoverflow.com/questions/4350076/can-system-math-cos-return-a-float

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!