在C#中,使我烦恼的是,没有“ Math.Cos”函数会返回浮点数。双精度值是您可以获取的唯一值,从而迫使您将其强制转换为浮点型。像这样:float val = (float)Math.Cos(someVal);
我需要使用浮点数,因为我正在严格使用浮点数的Direct3D中进行操作。浮点数是32位元,在图形世界(按现在的状态)更为常见。
我可以使用的C#中是否有任何功能可以像C ++一样处理浮点数?
我不想包装任何C ++东西,因为它需要在XNA和Linux for OpenGL上运行。
NOTE:如果代码没有将双精度浮点数转换为浮点数,将非常好。
如果不进行深入的数学讨论,您将无法编写自己的accurate 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静态类中的简单静态方法调用。
好,所以我运行了一些基准测试,以查看阅读“ 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;
}
}
我将创建一个MathCommonMethods类,该类的方法会将所有常用的返回类型转换为double形式的浮点数。从长远来看,这将节省您键入的时间。
就现有的函数而言,它以浮点数返回值,我还没有听说过。
如果精度对您的应用很重要,则在铸造时也应注意不要丢失精度。
如果要避免强制转换,则需要其他实现。如果您正在跨平台,则可以创建一个平台抽象层,在其中您可以基于平台放置不同的实现。这将有助于提高性能。如果性能不是问题(游戏就是这种情况),那么创建一个效用函数并执行强制转换是一个很好的解决方案。
从.NET Core 2.0(.NET Standard 2.1)(C#8.0)及更高版本开始作为内置函数,这是可能的。
您可以仅将MathF
类与内置常量或与float
类型一起使用的函数一起使用。
示例:
float cos = MathF.Cos(MathF.PI);
有关更多信息,请参见documentation on MSDN有关MathF
类型。