舍入的調和級數的和(一)

黃志斌發表於2018-03-22

題目

The Art of Computer Programming, Volume 1, Fascicle 1, MMIX, Donald E. Knuth, 2004. 習題 1.3.2'-30 (pages 48-49):

這道題目基本上等價於《計算機程式設計藝術·卷1:基本演算法(第3版)》習題 1.3.2-16(第 129 頁)。

解答

是充分小的正實數時,。因此,我們有

,則當且僅當 時,。因此,我們得到

最終,我們得到以下 MMIX 程式(根據書上的習題答案 (pages 109-110) 稍做修改):

簡要說明:

  • 程式中標號欄的 0H, 1H, 2H 的 H 意思是 Here,而運算元欄的 2F, 1B, 0B 的 F 和 B 意思分別是 Forward 和 Backward 。(See pages 35-36)
  • 第 2 至 14 行是 MMIXAL 偽操作碼,定義一些常量和變數等。
  • 第 17 至 46 行是外層迴圈。題目要求對於 1 ≤ n ≤ 10 計算 Sn,程式中對 -9 ≤ nn ≤ 0 進行迴圈。參考第 10 行。這是組合語言程式設計的常用技巧,可以節省一條 CMP 指令。
  • 第 15 行設定 nn 的初值為 -9,第 44 行在外層迴圈中將 nn 加 1。
  • 第 16 行設定 c 的初值為 20,第 45 行在外層迴圈中將 c 乘以 10。參考第 4 行。
  • 第 20 至 31 行的內層迴圈計算所求的和,結果在暫存器 s 中。
  • 第 32 至 43 行列印 s 的值。注意,s 是整數,正好是所求的和的 10n 倍。即小數點後正好有 n 位數字。
  • 第 32 至 33 行在小數點後第 n+1 位放一個 '\n',即換行符。
  • 第 35 至 41 行的內層迴圈從右到左得到 s 的各位數字。
  • 第 40 行判斷當前位置是否在小數點處,如是,再左移一格,以跳過小數點。

等價的 C 程式:

#include <stdio.h>

int main(void)
{
  for (long n = 0, s = 10, c = 20; ++n <= 10; s = (c *= 10) >> 1) {
    for (long mm, m = 1, r = 1; r != 0; m = mm)
      r = (c + m) / ((m + 1) << 1),
      s += r * ((mm = (c - 1) / ((r << 1) - 1)) - m);
    printf("%3ld.%0*ld\n", s / (c >> 1), n, s % (c >> 1));
  }
}

MMIX 程式的執行時間不到 1 秒,C 程式為 0.01 秒。這兩個程式的執行結果是相同的,都是:

  3.7
  6.13
  8.445
 10.7504
 13.05357
 15.356255
 17.6588268
 19.96140681
 22.263991769
 24.5665766342

相關文章