zezba9000
zezba9000

Reputation: 3383

Can "System.Math.Cos" return a (float)?

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.

Upvotes: 18

Views: 15065

Answers (5)

picolino
picolino

Reputation: 5459

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.

Upvotes: 13

zezba9000
zezba9000

Reputation: 3383

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

Upvotes: 5

IAbstract
IAbstract

Reputation: 19881

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.

Upvotes: 7

Chuck Callebs
Chuck Callebs

Reputation: 16441

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.

Upvotes: 4

codekaizen
codekaizen

Reputation: 27429

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.

Upvotes: 2

Related Questions