Может ли "System.Math.Cos" возвращать (float)?
В С# мне кажется, что нет функции "Math.Cos", которая возвращает float. Двойное значение - это единственное значение, которое вы можете вернуть, тем самым вынуждая его использовать его для поплавка.
Например:
float val = (float)Math.Cos(someVal);
Мне нужно использовать float, потому что я делаю материал в Direct3D, который строго использует float.
Поплавки гораздо чаще встречаются в мире графики (как сейчас), потому что они 32bit.
Есть ли какая-либо функциональность внутри С#, которую я могу использовать, просто будет обрабатывать такие поплавки, как С++?
Я не хочу обертывать какие-либо материалы на С++, потому что это нужно запускать на XNA и Linux для OpenGL.
ПРИМЕЧАНИЕ. Было бы неплохо иметь код, в котором не было бы двойного поплавка.
Ответы
Ответ 1
Не вдаваясь в какую-то углубленную математику, вы не сможете написать свою собственную точную функцию 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 будут медленнее, поскольку zezba подтвердил в своем тестовом коде (я не знал, что делегаты будут намного медленнее). Самый быстрый - это прямой бросок для плавания. Средней почвой были бы простые вызовы статических методов в статическом классе MathF.
Ответ 2
Я бы создал класс MathCommonMethods с методами, которые бы конвертировали все часто используемые типы возвращаемых данных в float в leiu of double. Это сэкономит вам некоторую типизацию в долгосрочной перспективе.
Насколько существует существующая функция, возвращающая значение как float, я не слышал об этом.
Вы также должны быть осторожны при бросании, чтобы не потерять точность, если точность важна для вашего приложения.
Ответ 3
Хорошо, поэтому я запустил несколько тестов, чтобы узнать, какой метод был самым быстрым после чтения "dboarman". К сожалению, это не так, потому что это невозможно сделать без использования строгого С#, а самый быстрый метод - просто бросить на место, так что я забочусь о скорости, поскольку в основном для игр плохо придерживаться старого метода литья.
Эти тесты были скомпилированы с использованием следующих спецификаций::
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
Если вы хотите избежать кастинга, вам понадобится другая реализация. Если вы делаете кросс-платформу, вы можете создать слой абстракции платформы, где вы можете поместить различные реализации на платформе. Это поможет в производительности. Если перфоманс не является проблемой (это всегда имеет место в играх), то создание функции утилиты и выполнение кастинга есть хорошее решение.