湊整數實作思路與方法

前陣子在嘖嘖看到「湊整數」功能,比如結帳時 1359 元,按下湊整數按鈕後會變成 1400 元,這其實是個蠻有趣的功能,但實作時才發現湊整數並不好做,有很多非技術面的顧慮,這邊就紀錄我在實作所遇到的問題、過程以及最後的解法吧!

觀察嘖嘖的湊整數功能大概分成兩種策略,第一種是最首位的數字進位,例如 1001 會直接變成 2000,3499 會變成 4000,而小於 1000 的數字統一進位到 1000 元,第二種則是幸運數的概念,持續點擊「湊整數」會出現一些並非整數的數字,例如 6666、8888 等等。

我個人認為嘖嘖的幸運數字很有趣,但首位直接進位的做法真的不知道是 Bug 還是故意的… 我買 1001 的東西結果湊個整數變成 2000,或是買 199 元變成 1000 元,這其實有點誇張,我個人認為湊整數的第一個限制就是:「湊整數的溢價不能超過原金額」,例如 399 元的商品,可以湊成 400、500,但不能變成 1000 元,因為 1000 – 399 就溢價了 601 元,比原商品還貴!

湊整數最開始我的想法是從開頭第一位或第二位進位,例如 199 的第一位是 1,則進位到 2,其餘數字補 0 變成 200,依照這方法: 10599 會變成 20000 或 11000,看起來蠻合理的對吧? 但有個問題哦! 這種做法有可能導致「湊整數的溢價超過原金額」,對消費者而言是件蠻奇怪的事情。

後來發現我把事情想複雜了,其實湊整數最基本可以用除法來達成,透過除法取到百位數後無條件進位,在乘一百來還原數字,這方法的好處是可以控制湊整數只到百位數,不會造成太誇張的湊整數現象,例如 1999 / 100 = 19.99,無條件進位後變成 20,接者 20 * 100 = 2000,就完成基本的湊整數了,用這方式可以得到一些結果如下:

  • 199 => 200
  • 799 => 800

以 JS 示範程式碼:

Math.ceil(1999 / 100) * 100

這樣的做法,可以把湊整數的範圍控制在百位數,實作又簡單,但試想下面這些數字,你該如何湊整數呢?

  • 15000
  • 17500
  • 1500

像上面的情況,消費者的金額本身已經是整數了,遇到這情況該怎辦?

最開始我認為如果數字已經是整數,理所當然就不用再進位了,但仔細想想如果一個消費者今天明知數字是整數,為何還要按下湊整數按鈕呢? 代表他認為這個數字還不夠整數吧! 或是覺得錢多想再多付一點(笑) 既然如此我們當然要成全他的願望囉,這邊我選擇從數字的右邊開始找尋第一個「不是零」的數字,遇到之後就將這位數字進位,例如:

  • 15000 => 16000

從右邊數,第一個遇到的非零數是 5 ,所以進位後變成 6,其餘數字補上就是 16000。

另一種做法概念類似,但數字會補在第一個不是零的前一位,例如:

  • 15000 => 20000

這兩種作法基本上就看你的狠心程度決定該用哪種,前提假設就是「使用者明知這是整數,再按一下的原因是?」

附上這個做法的 JS Code,分成兩階段,如果數字「不是百位的整數」就用進位到百位的做法,否則就用第一個非零數進位的做法,這邊用正規表達式來判斷第一個非零數的位置。

function happy_money(num) {
  // 如果已經進位到百位整數
  if(Math.floor(num / 100) == num/100) {
  // 從右邊算第一位非零數的位置
    var posi = /[1-9][0]*$/.exec(Number(num).toString())[0].length - 1;
    return num + Math.pow(10,posi);
  } else {
    // 123 -> 200
    // 123001 -> 123100
    return Math.ceil(num / 100) * 100;
  }
}

如果你對幸運數有興趣的話,它的原理基本上是先預建一個陣列來存放許多的幸運數字,接下來就看消費者的金額跟哪個幸運數最接近,就跳到該數字。

我自己在測試時,習慣用這幾個數字做測試,觀察是否和預期相同或做調整:

  • 99
  • 199
  • 150
  • 1500
  • 20000
  • 2010100

最終該選擇什麼方式,或是不同方式混用,其實要視使用場景而定,例如單價十萬元的商品,湊個 1000 元內的整數看似還好(?) 又或者公益類型的專案,使用幸運數、隨機數或進位較多也沒有關係,但低單價的商品你總不好意思湊到太貴吧。

在〈湊整數實作思路與方法〉中有 2 則留言

  1. 原本以為是購買東西然後取整,這樣應該很多人不會去點 ( X
    原來是募款會用到 覺得蠻實用的 XD

    1. 嘿呀哈哈,如果是網路購物應該不會有人想點XD
      主要是群眾募資、募款等等場景會有需求

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料