昨天看到一段程式碼[1]:
我一看,就懂了:這程式碼定義了一個叫做width的函式,這個函式接受三個引數,其中後兩個有預設值,如果三個引數中的第一個大於等於 2 ,並且第二個不等於 0 ,並且第三個小於 19 ,那麼遞迴呼叫width(n, d % n * 10, w+1)並返回呼叫結果加 1 ,否則返回 0 。
比如說計算width(8):
不管引數是多少,照這樣都能算出結果,很簡單,對吧。
但是今天看了其他兩個版本的實現,才發現我之前根本不懂這個函式在做什麼。
這並不是什麼高大上的演算法,只是小學除法而已。d是被除數,n是除數,w是結果的位數。
每次呼叫都會計算餘數,然後在餘數末尾加 0 ,把這當成新的被除數。如果被除數是 0 ,那麼表示之前已經除盡,直接返回。
例如,要計算 10 除以 8:
因為每呼叫一次都增加一個 0,所以遞迴呼叫的次數等於商的位數。如果發現商的位數超過 19 位,就不再繼續。除數是 0 或 1 時,結果是 0 。
最後結果就等於 1/n 對應的小數在十進位制中的小數位數。
對比一下:
定義一個叫做 width 的函式,這個函式接受三個引數,其中後兩個有預設值,如果三個引數中的第一個大於等於 2 ,並且第二個不等於 0 ,並且第三個小於 19 ,那麼遞迴呼叫width(n, d % n * 10, w+1)並返回呼叫結果加 1 ,否則返回 0 。
和
width(n) 返回 1/n 在十進位制中的小數位數,當位數大於等於 19 時返回 19 ,當 n 為 0 或 1 時返回 0。
似乎這兩段都正確描述了 width 的功能,都能算作“看得懂”,但這兩個“懂”大概是不一樣的。
那麼題主是哪種呢?
參考^這段程式碼來自:https://github.com/llvm/llvm-project/blob/a59283a74529c74a8ee8682f9acf9d993f7cda08/libcxx/include/chrono#L2772-L2777
最新評論