【JS】Pontaの実質還元率をJavaScriptで求める
こんにちは!今日はJavaScriptを用いたアルゴリズムについて身近なPontaを例に書きます。
Ponta
Pontaとはローソンで出すと100円で1ポイント貰えるあれです。 説明不要ですね。
代金からもらえるPontaを求める関数はこんな感じ。
const getPonta = price =>
price / 100 | 0
console.log(getPonta(100))// 1
console.log(getPonta(200))// 2
|0は小数点以下切り捨てです。
ローソンで1億円買ったら
Pontaは還元率1%。1億買ったらPontaは1,000,000円貰えるのでしょうか。
試してみよう
console.log(getPonta(100000000))// 1000000
貰えました。しかし...
Ponta端数問題
Pontaは端数切り捨てです。100円でも199円でも同じ。
console.log(getPonta(100))// 1
console.log(getPonta(199))// 1
つまり何が言いたいのか
Pontaを例にしましたが、準通貨の還元率は往々にして切り捨て方式だったりします。
クレジットカードで「還元率○○%!」ってあるやつは 実際もっと低かったりすることもある、ということです:(
クレジットカードを選ぶ時はその辺にも気をつけるといいですよ!!
Pontaの還元率を求める
え?終わりじゃないの?
もう言いたいことは終わりましたが、技術ブログなのでここからがおまけ本題です。
じゃあ実際にローソンで1億円分買って検証してみましょう。JavaScriptで。
前提条件
- ローソンで1億円分買う。
- 1億円に到達するまで買い続ける。
- Pontaは100円で1ポイント貯まるとする。
- 1回の買い物は0円(トイレ借りるだけ)〜1,000円(大人がコンビニで躊躇せずに使える)とする。
- 1億42円とか最後がオーバーするのはok。
やっていきましょう。
アルゴリズム
いくつかの関数を考えてみます。
さっき作ったgetPonta
const getPonta = price =>
price / 100 | 0
次に0〜1,000をランダムで返す関数。
const getPayment = () =>
Math.random() * 1000 | 0
配列の合計を求める関数。
const sum = payments =>
payments.reduce((total, payment) =>
total + payment
)
1億円まで買い続ける関数shop at lawson。
延々と再帰を行い買い物を続け、毎回支払った金額の配列を [183, 744, 938...]みたいな感じで作ります。
const shopAtLawson = payments =>
sum(payments) >= 100000000
? payments
: shopAtLawson([... payments, getPayment()])
↑の支払った金額から合計Pontaを求める関数。
const sumTotalPontas = totalPayments =>
totalPayments.reduce((total, payment) =>
total + getPonta(payment)
,0)
最後に、還元率を求める式。
const rate = totalPoints / 1000000 * 100
これらの関数を用いて、答えを求めていきます。
答え(注: 糞重い)
注: 糞重い
const getPonta = price =>
price / 100 | 0
const getPayment = () =>
Math.random() * 1000 | 0
const sum = payments =>
payments.reduce((total, payment) =>
total + payment
)
const shopAtLawson = payments =>
sum(payments) >= 100000000
? payments
: shopAtLawson([... payments, getPayment()])
const totalPayments = shopAtLawson([0])
const sumTotalPontas = totalPayments =>
totalPayments.reduce((total, payment) =>
total + getPonta(payment)
,0)
const totalPoints = sumTotalPontas(totalPayments)
const rate = totalPoints / 100000000 * 100
console.log(rate)// 0.9010
今回のケースでは還元率は1%ではなく0.9%に近似されました。
数学的な答え(多分)
実質還元率
= 還元率 -
(((端数の最小値 + 最大値) / 2 )
/ ((支払い額の最小値 + 最大値) / 2))
= 1 - (((0 + 100) / 2) / ((0 + 1000) / 2))
= 0.9
結論
- ポイントの切り捨てに注意しよう。特に少額の支払いをちょいちょいするやつ。
- 再帰関数は糞重い
今日はいい記事が書けた!ハッピー<3<3<3
LINK
TAGS
LATESTS
POPULAR
- CSS2021/04/29【CSS】右寄せの方法は結局flexが一番良さそう
- React2020/07/13【JS】Reactのstyleの使い方、書き方いろいろ
- Payment2021/10/16GooglePayでVisaタッチを使う時に知っておきたい過酷な現実【追記あり】
- Others2021/07/11Slackに予約投稿機能ができて嬉しいけどそれでもまだ少し不満な理由【追記あり】
- CSS2020/04/30【CSS】tailwind.cssでよく使うデザインパターン
- CSS2019/03/30【CSS】100vhは「一画面」ではないという罠
- CSS2020/06/09【CSS】max-font-sizeやmin-font-sizeを使いたくなったら
- Vue2019/06/29【JS】Vueの:classの書き方3通り
- JavaScript2020/09/02【JS】yarnの長所とyarnからnpmに戻ってきた理由
- React2020/06/04【JS】ReactのclassNameの色々な書き方紹介