再次感謝那些參與的人,並感謝您對這篇遲到的帖子的耐心等待。 每個人都能夠完成挑戰。 對於非 JMP 員工來說,最大的添加數字(約 200 萬位數字)和最大的 1,000 位數字列表(約 2,000 個項目)挑戰均被以下方法擊敗: @大衛_伯納姆。 對於員工條目,5秒內新增的最大兩個數字約為2200萬( @brady_brady和@Craige_Hales )最大的清單大約有 61,500 個元素(挑戰3 範例3.JSL )。 這些腳本已發佈在下面。
以下是三個挑戰的總分:
讓我們從涉及兩個數字的運算開始。 挑戰 3 範例 1 – Slow.JSL提供了與大多數條目類似的實作:
- 確定數字是否相同(加法)或相反(減法)。
- 解析數字字串。
- 執行加法/減法運算。
- 連接結果以建立答案。
加法和減法運算是在單一函數或多個函數中執行是風格問題,並且只影響程式的清晰度和可讀性,而不影響執行時間。 然而,產生巨大差異的是如何解析輸入數字並將其重新組合在一起。 在循環各個數字之前解析輸入字串(挑戰 3 範例 1 – Faster.JSL )而不是在循環內,運算速度提高了約 5 倍(2.28 秒 vs. 2 個 16,000 位數字相加的 0.464 秒)。 透過將結果收集到清單中,然後連接末尾的項目,從循環內部刪除單一字串連接,速度加快 10 倍以上(0.04054 秒) - 請參閱(挑戰 3 範例 1 -fastest.JSL)。
在我們討論如何使其更快之前,我們應該討論在清單中添加數字。 幾乎每個人都通過一次迭代列表中的一項,並將每一項添加到運行總計中來處理這個問題。 雖然這最終不是最快的方法,但它可以變得異常快(挑戰 3 - Hales.JSL在 5 秒內增加了 51,000 個 1000 位數字)。 與大多數操作一樣,提高速度的關鍵是在所有條件相同的情況下最大限度地減少操作數量。 在提供的範例中,挑戰3 範例2.JSL ,解決方案是將進位/借位操作從每對數字一次設定減少到總共三組。 這是透過以下方式完成的:
- 將輸入數字載入到兩個矩陣中,一個用於正數,一個用於負數。
- 使用分別添加每個矩陣電壓總和,對兩個結果矩陣執行一組進位運算。
- 從較大的數字中減去較小的數字。 對結果執行一次借用操作。 最後的減法是使用上面討論的二數演算法來執行的。
透過在進位/借位操作期間一次考慮多於一位數字,可以使兩位數和清單操作變得更快。 這在兩個地方都完成了挑戰 3 - Hales.JSL和挑戰 3 - Brady.JSL 。 雖然自然傾向是用一個數字進行加/減/進位/借位,但只要不發生溢出,只要稍微巧妙一點,該過程就可以推廣到盡可能多的數字。 在聯合管理計劃,對於兩個數字的情況,這將是 14 位數字,並且14 – 樓層(Log10(清單大小– 1))數位, 在哪裡清單大小在清單情況下,是輸入清單中的項目數。 要理解為什麼會這樣,請回想一下溢出發生在大約 9e16 處。 將兩個最大的 15 位數字(15 個 9)相加會導致溢位錯誤。 將兩個最大的 14 位數字相加則不會。 同樣,當執行 11 到 100 次(準確地說是 91 次)時,將 9,999,999,999,999 添加到自身將導致溢出。
作為其工作原理的範例,請考慮添加三個數字,其中每個數字排列在 14 個寄存器中:
11 99999999999999
22 99999999999999
33 99999999999999
將第一個暫存器(14 個 9)的值相加得出
2 99999999999997
攜帶 2 並對第二個暫存器求和得到
68
最終的數字是
68 99999999999997
這種方法的應用在挑戰3 範例3.JSL 。 增加兩個 200 萬位數的平均處理時間從 4.7 秒縮短到 0.82 秒,速度提高了 5 倍以上。 額外的調整可以將速度提高 2 倍,如下所示挑戰 3 - Hales.JSL和挑戰 3 - Brady.JSL增加 10,000 個 1000 位數字所需的時間從 4.5 秒減少到 0.88 秒 (5 倍)。 這導致最快的列表添加方法。
2020 年 7 月 20 日:又修復了一個錯誤,這次是挑戰3 範例3.JSL 。 新增了對所有三個範例 1 檔案使用矩陣參數時的警告訊息(直到範例 2 才實現)。
2020 年 7 月 17 日:我在挑戰 3 範例 1 腳本中發現了另一個錯誤,所有三個錯誤都已修復和替換。
2020 年 7 月 16 日: 我更換了腳本挑戰 3 範例 1 - Slow.JSL和挑戰 3 範例 1 - Faster.JSL因為它們末尾包含一行會導致問題(它們引用了我用來測試程式碼的表)。 如果您已下載這些檔案但尚未自行解決問題,請取代舊副本。