1. 程式人生 > >一條語句計算所有遞增序列的結果

一條語句計算所有遞增序列的結果

1.遞增序列的概念:

一串數的序列,相領兩個數之間的差值是固定的,則此數列遞增序列,如:

1,2,3,4,5,6,7,8,9,10(差1) 1,3,5,7,9,11(差2)

 

大家一般都會了解,它的規律是第1個數與倒數第1個數的和,與第二個數與倒數第二個數的和是一樣的。這樣可以有這樣的計算方法:

(Begin + End ) * ( End - Begin ) / 2 就會計算出它的所有數值的總和。

 

但以上情況是在數值總數量為偶數是有效的,如果是奇數,則需要加入未計算的數值:

( (Begin + End ) * ( End -Begin ) ) / 2 + ( Begin + ( End - Begin ) / 2 + 1 ),這裡的第二個括號之中就是未加入的數值。

 

以上算式為了簡單表示,沒有加入對數列起點和結果是否在計算範圍之中的考慮,如果起點和結束點都在計算範圍,長度應+1,如果結束點不在計算範圍,和值應-1,如下:

( ( Begin + End - 1 ) * ( End -Begin ) 或

( ( Begin + End ) * ( End - Begin + 1 )

 

這裡一個數列和計算普通方法:

 

 Begin是起點,End是結束點,Space是間隔:

 static ULONG SerialNumSum2( ULONG Begin, ULONG End, ULONG Space )
{
 ULONG Sum = 0;
 INT32 i;
 for( i = Begin; i <= End; i += Space )
 {
  Sum += i;
 }

 return Sum;
}

 

這裡是使用簡算方法實現的方法,並且經過簡化只使用一條語句來完成:

 

#define ALIGNED_END( begin, end, space ) ( end - ( ( end - begin ) % space ) )//計算對齊值
static ULONG SerialNumSum( ULONG Begin, ULONG End, ULONG Space )
{
 return ( ( INT32 )( Begin - End ) > 0 ) ? 0 :
  ( ( ( ( End - Begin ) / Space + 1 ) % 2 ) == 0 ) ?
   ( Begin + ALIGNED_END( Begin, End, Space ) ) * ( ( ( ( End - Begin ) / Space + 1 ) ) >> 1 ) : //偶數
   ( Begin + ALIGNED_END( Begin, End, Space ) ) * ( ( ( ( End - Begin ) / Space + 1 ) ) >> 1 ) + Begin + ( ( ( ( ( ( End - Begin ) / Space + 1 ) ) >> 1 ) ) * Space ); //奇數
}

 

可以用以下方法測試一下,結果都是正確的:

 

 for( int i = 0; i < 100; i ++ )
 {
  for( int j = 0; j < 1000; j ++ )
  {
   for( int k = 0; k < 100; k ++ )
   {
    ULONG TimeQuickSumBegin = GetTickCount();
    ULONG Result = SerialNumSum( i, j, k + 1 );
    ULONG TimeQuickSumEnd = GetTickCount();
   
    ULONG TimeSumBegin = GetTickCount();
    ULONG Result2 = SerialNumSum2( i, j, k + 1);
    ULONG TimeSumEnd = GetTickCount();

    printf( "Begin %d, End %d, Sapce %d, quick sum is %d time is %d, normal sum is %d time is %d /n",
     i,
     j,
     k + 1,
     Result,
     TimeQuickSumEnd - TimeQuickSumBegin,
     Result2,
     TimeSumEnd - TimeSumBegin );
   }
  }
 }