2009-08-18 81 views
9

我在我的代码(C#/ WPF)中对性能非常敏感的部分,我需要以尽可能快的方式在两个System.TimeSpan值之间执行模运算。如何使用System.TimeSpan值实现模数运算,无需循环?

这段代码将每秒运行数千次,我非常希望避免使用手动循环计算 - 不惜一切代价。

2周的时间跨度之间的模数的想法似乎有点怪异,所以让我来解释 -
说我们有
时间跨度A = 1分30秒
时间跨度B = 20秒

这里将是常见的操作和它们的合理结果的列表:

A + B =(时间跨度)1分50秒

A - B =(时间跨度)1分10秒

A * B =没有合理的计算方法
我们应该可以用乘以TimeSpan整数。 A * 5 =(TimeSpan)7分钟30秒
Microsoft尚未在TimeSpans和整数之间实现乘法。

A/B =(int)4或(double)4.5
此操作不是直接在.NET框架中实现的,但它非常有意义。
有在A. 4.5 B的(4.5 * 20 = 90)

A%B =(时间跨度)10秒
鉴于合理时间跨度划分,时间跨度模量应该是相当直接的。
A/B 确实等于(int)4 余数(TimeSpan)10秒。商和余数是不同的数据类型,这可能实际上是微软没有直接实现这一点的原因。

我需要找到一种有效的方法来计算这个没有循环。通常我不会反对短循环,但是这些TimeSpans可能会有很大的不同。 TimeSpans之间的指数差越大,商数越大。商数越大,“分环”必须执行的迭代越多。这是我在我的应用程序的这部分中不允许的依赖项。

这样做有什么想法吗?

+0

答案非常简单。我觉得自己很笨,哈哈。谢谢! – Giffyguy 2009-08-18 18:55:16

+1

一旦你有答案,一切看起来很简单。 – 2009-08-18 19:42:28

回答

23

乘法很容易:

TimeSpan a5 = TimeSpan.FromTicks(A.Ticks * 5); 

同样的A/B:

double aOverB = (double)A.Ticks/B.Ticks; 

和A%B:

TimeSpan aModB = TimeSpan.FromTicks(A.Ticks % B.Ticks); 

演示:

using System; 

class Test 
{ 
    static void Main() 
    { 
     TimeSpan a = TimeSpan.FromSeconds(90); 
     TimeSpan b = TimeSpan.FromSeconds(20); 

     TimeSpan a5 = TimeSpan.FromTicks(a.Ticks * 5); 
     double aOverB = (double)a.Ticks/b.Ticks; 
     TimeSpan aModB = TimeSpan.FromTicks(a.Ticks % b.Ticks); 

     Console.WriteLine(a5); 
     Console.WriteLine(aOverB); 
     Console.WriteLine(aModB); 
    } 
} 

输出:

00:07:30 
4.5 
00:00:10 
+0

不会产生大量垃圾等待垃圾处理吗?用毫秒或滴答作为长时间记录的时间最终会更好吗? – ADB 2009-08-18 19:03:40

+6

TimeSpan是一个结构,因此不会燃烧GC。 – user7116 2009-08-18 19:05:05

4

如果您可以将时间跨度转换为其代表的秒数,则可以对这些值进行修改,然后再进行转换。

5

会像

new TimeSpan(A.Ticks % B.Ticks)) 

给你你想要的结果? Ticks会是做这项工作的合适单位吗?也许你需要将范围转换为秒或毫秒或其他东西。我不知道你的申请是什么。

3

我不会直接与时间跨度对象做到这一点,但使用蜱能力。

就是这样。

TimeSpan oSpan = new TimeSpan(0, 1, 20, 0, 0); 
TimeSpan oShort = new TimeSpan(0, 0, 20, 0, 0); 
long modRemainder = oSpan.Ticks % oShort.Ticks; 
TimeSpan oRemainderSpan = new TimeSpan(modRemainder); 

你可以将它凝聚成1步,但我这样做是为了说明。它可以很容易地做任何你想要的数学运算。

1

我能想到的最好的方法就是使用TotalSeconds属性并对其进行取模。但是,它们是Double,允许使用小数值,因此可能无法达到您正在寻找的确切值。你总是可以得到整个部分并对它们进行模数化,但是由于你担心速度,我担心这可能会太慢,以至于每秒必须运行数百次的操作。