float f = 5.13;
double d = 5.13;
float fp = f - (float)Math.floor(f);
double dp = d - Math.floor(d);
每次调用外部函数有没有更快的方法?
答案 0 :(得分:5)
“外部功能”?
System.Math内置于mscorlib!
这实际上是最快的方法。
答案 1 :(得分:3)
你可以将f转换为一个可以修剪小数部分的int。这假设你的双打属于整数范围。
当然,抖动可能足够聪明,可以将Math.floor优化为一些内联的asm,它可以比执行转换为int更快,然后再转换为浮动。
您是否实际测量并验证过Math.floor的性能是否会影响您的程序?如果还没有,那么在你知道这个问题之前,你不应该费心去做这个级别的微优化,然后根据原始代码测量这个替代方案的性能。
编辑:这看起来更快。使用Math.Floor()时,以下代码需要717ms,在发布模式下,我的机器上的int cast代码需要172 ms。但同样,我怀疑性能提升真的很重要 - 为了让这个可以测量我必须进行100米迭代。此外,我发现Math.Floor()更具可读性和显而易见性,未来的CLR可以为Math.Floor发出更优化的代码并轻松击败这种方法。
private static double Floor1Test()
{
// Keep track of results in total so ops aren't optimized away.
double total = 0;
for (int i = 0; i < 100000000; i++)
{
float f = 5.13f;
double d = 5.13;
float fp = f - (float)Math.Floor(f);
double dp = d - (float)Math.Floor(d);
total = fp + dp;
}
return total;
}
private static double Floor2Test()
{
// Keep track of total so ops aren't optimized away.
double total = 0;
for (int i = 0; i < 100000000; i++)
{
float f = 5.13f;
double d = 5.13;
float fp = f - (int)(f);
double dp = d - (int)(d);
total = fp + dp;
}
return total;
}
static void Main(string[] args)
{
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
// Unused run first, guarantee code is JIT'd.
timer.Start();
Floor1Test();
Floor2Test();
timer.Stop();
timer.Reset();
timer.Start();
Floor1Test();
timer.Stop();
long floor1time = timer.ElapsedMilliseconds;
timer.Reset();
timer.Start();
Floor2Test();
timer.Stop();
long floor2time = timer.ElapsedMilliseconds;
Console.WriteLine("Floor 1 - {0} ms", floor1time);
Console.WriteLine("Floor 2 - {0} ms", floor2time);
}
}
答案 2 :(得分:3)
“我们应该忘记效率低,大约97%的时间说:过早 优化是万恶之源。“
因此,除非您对应用程序进行基准测试并发现此操作是瓶颈的正面证据,否则不要费心优化这些代码。
答案 3 :(得分:2)
嗯,我怀疑你会获得任何真实世界的性能提升,但根据Reflector Math.Floor是这样的:
public static decimal Floor(decimal d)
{
return decimal.Floor(d);
}
可以说是
double dp = d - decimal.Floor(d);
可能会更快。 (编译器优化使我知道的整点意义不大......)
对于那些可能有兴趣将其理解为十进制的人。地板是:
public static decimal Floor(decimal d)
{
decimal result = 0M;
FCallFloor(ref result, d);
return result;
}
FCallFloor是对非托管代码的调用,因此你几乎处于“优化”的极限。
答案 4 :(得分:2)
对于Decimal
,我建议忽略所有人不要改变它并尝试使用Decimal.Truncate
。无论它是否更快,它是一个专门用于你想要做的事情的功能,因此更清晰。
哦,顺便说一句,它更快:
System.Diagnostics.Stopwatch foo = new System.Diagnostics.Stopwatch();
Decimal x = 1.5M;
Decimal y = 1;
int tests = 1000000;
foo.Start();
for (int z = 0; z < tests; ++z)
{
y = x - Decimal.Truncate(x);
}
foo.Stop();
Console.WriteLine(foo.ElapsedMilliseconds);
foo.Reset();
foo.Start();
for (int z = 0; z < tests; ++z)
{
y = x - Math.Floor(x);
}
foo.Stop();
Console.WriteLine(foo.ElapsedMilliseconds);
Console.ReadKey();
//Output: 123
//Output: 164
编辑:修正了我的解释和代码。
答案 5 :(得分:0)
它是静态的,所以这应该非常快,没有任何对象可以站起来。您可以随时进行数学水平计算,但除非您有一些认真使用该功能。可能floor()方法已经这样做了,但如果你需要一些非常快的东西,你可以内联它并删除支票等,但在C#中这不是你最大的性能问题。