一條語句計算所有遞增序列的結果
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 );
}
}
}