前陣子在嘖嘖看到「湊整數」功能,比如結帳時 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 元內的整數看似還好(?) 又或者公益類型的專案,使用幸運數、隨機數或進位較多也沒有關係,但低單價的商品你總不好意思湊到太貴吧。
原本以為是購買東西然後取整,這樣應該很多人不會去點 ( X
原來是募款會用到 覺得蠻實用的 XD
嘿呀哈哈,如果是網路購物應該不會有人想點XD
主要是群眾募資、募款等等場景會有需求