Может ли System.Math.Cos возвращать (float)? - PullRequest
14 голосов
/ 04 декабря 2010

В C # мне не нравится, что нет функции "Math.Cos", которая возвращает float. Двойное значение - это единственное значение, которое вы можете получить обратно, что вынуждает вас разыграть его с плавающей точкой Вот так:
float val = (float)Math.Cos(someVal);

Мне нужно использовать поплавки, потому что я делаю вещи в Direct3D, который строго использует поплавки. Плавания гораздо более распространены в графическом мире (как он есть сейчас), поскольку они 32-битные.

Есть ли какая-либо функциональность в C #, которую я могу использовать, которая будет просто обрабатывать операции с плавающей точкой, как это делает C ++?

Я не хочу оборачивать какие-либо вещи на C ++, потому что они должны работать на XNA & Linux для OpenGL.

ПРИМЕЧАНИЕ : Было бы неплохо иметь код, который не приводил бы к двойному значению с плавающей точкой.

Ответы [ 4 ]

6 голосов
/ 04 декабря 2010

Не вдаваясь в углубленную математику, вы не сможете написать свою точную функцию 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);
}

Как указали другиеделегаты Func будут медленнее, как подтвердил Зезба в своем тестовом коде (я не знал, что делегаты будут намного медленнее).Самый быстрый - прямой бросок на плавание.Срединной точкой были бы простые статические вызовы методов в статическом классе MathF.

5 голосов
/ 05 декабря 2010

Хорошо, поэтому я провел несколько тестов, чтобы увидеть, какой метод был самым быстрым после прочтения ответа "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 голосов
/ 04 декабря 2010

Я бы создал класс MathCommonMethods с методами, которые конвертировали бы все часто используемые типы возвращаемых значений в числа с плавающей точкой в ​​виде числа значений типа double. Это сэкономит вам время при наборе текста.

Что касается существующей функции, которая возвращает значение в виде числа с плавающей запятой, я не слышал о ней.

Вы также должны быть осторожны при касте, чтобы не потерять точность, если точность важна для вашего приложения.

2 голосов
/ 04 декабря 2010

Если вы хотите избежать приведения, вам понадобится другая реализация.Если вы делаете кроссплатформенность, вы можете создать уровень абстракции платформы, где вы можете размещать различные реализации на основе платформы.Это поможет с производительностью.Если перф не является проблемой (это всегда имеет место с играми), тогда создание вспомогательной функции и выполнение кастинга - это хорошее решение.

...