数 (お金) を x 数に均等に分割するにはどうすればよいですか?
1000
or 100.2
orなど、112.34
その数値をすべて均等に x 部分に分割できるようにしたいのですが、奇数でない場合は、最後の数値に余分な数値がかかります。
例えば
3856 / 3
1285.33
1285.33
1285.34
数 (お金) を x 数に均等に分割するにはどうすればよいですか?
1000
or 100.2
orなど、112.34
その数値をすべて均等に x 部分に分割できるようにしたいのですが、奇数でない場合は、最後の数値に余分な数値がかかります。
例えば
3856 / 3
1285.33
1285.33
1285.34
他の回答のレビュー
ここで提供されている解決策を再検討した後、奇妙な結果が得られることに気付きました。
@GeorgeMauler'sdivideCurrencyEqually
は、元の質問で提供された入力で動作するようです。しかし、それらを少し変更すると、非常に奇妙な結果が得られます...
// it appears to work
divideCurrencyEvenly(10,3)
=> [ '3.33', '3.33', '3.34' ]
// wups ...
divideCurrencyEvenly(10,6)
=> [ '1.67', '1.67', '1.67', '1.67', '3.32' ]
// hmm this one works ...
divideCurrencyEvenly(18,5)
=> [ '3.60', '3.60', '3.60', '3.60', '3.60' ]
// wups ...
divideCurrencyEvenly(100,7)
=> [ '14.29', '14.29', '14.29', '14.29', '14.29', '28.55' ]
@Barmarのソリューションは少しパフォーマンスが良いようですが…まあ少し…
// it appears to work
divide(10,3)
=> [ '3.33', '3.33', 3.34 ]
// acceptable, i guess
divide(10,6)
=> [ '1.66', '1.66', '1.66', '1.66', '1.66', 1.700000000000001 ]
// hmm, not so good, but still acceptable
divide(18,5)
=> [ '3.60', '3.60', '3.60', '3.60', 3.5999999999999996 ]
// as acceptable as the last two, i guess
divide(100,7)
=> [ '14.28', '14.28', '14.28', '14.28', '14.28', '14.28', 14.320000000000007 ]
のような数値は、JavaScript で浮動小数点演算がどのように機能するか3.5999999999999996
により、ほとんど許容されます。
しかし、私が最も気になるdivide
のは、それが混合型の配列(文字列と浮動小数点数)を提供していることです。また、数値は出力で (正しい精度に) 丸められていないため、結果を紙の上で合計した場合、元の入力に戻ることはありません。numerator
つまり、結果を丸めない限り、 .
そして私たちは今も平等のために戦っています…
私の最後の不満は、上記のソリューションの両方にも存在します。結果は、可能な限り均等に近い分布を表していません。
精度 2 で 100 を 7 で除算すると、@Barmar のソリューション (丸めの問題が修正されている) は次のようになります。
[ '14.28', '14.28', '14.28', '14.28', '14.28', '14.28', 14.32 ]
これらが人で、数字がお金を表している場合、1 人が4 ペニー以上支払うべきではありません。代わりに、 4 人が1 ペニー多く支払う必要があります …
[ 14.29, 14.29, 14.29, 14.29, 14.28, 14.28, 14.28 ]
それは可能な限り同等に近いです
振り出しに戻って
解決策に不満があったので、自分で作成しdistribute
ました。
これには、 precision p
、divisor d
、およびnumerator の3 つのパラメーターがありますn
。
分子をスケーリングし、 である最大の整数を見つけq
ますq * d <= n
。剰余除算を使用すると、寄与する必要がある「スライス」の数がわかりますq+1
。最後に、各q
orq+1
が縮小されて出力配列に入力されます。
const fill = (n, x) =>
Array (n) .fill (x)
const concat = (xs, ys) =>
xs .concat (ys)
const quotrem = (n, d) =>
[ Math .floor (n / d)
, Math .floor (n % d)
]
const distribute = (p, d, n) =>
{ const e =
Math .pow (10, p)
const [ q, r ] =
quotrem (n * e, d)
return concat
( fill (r, (q + 1) / e)
, fill (d - r, q / e)
)
}
console .log
( distribute (2, 3, 10)
// [ 3.34, 3.33, 3.33 ]
, distribute (2, 6, 10)
// [ 1.67, 1.67, 1.67, 1.67, 1.66, 1.66 ]
, distribute (2, 5, 18)
// [ 3.6, 3.6, 3.6, 3.6, 3.6 ]
, distribute (2, 7, 100)
// [ 14.29, 14.29, 14.29, 14.29, 14.28, 14.28, 14.28 ]
)
精度をパラメーター にp
しました。これは、小数点以下の桁数を制御できることを意味します。Δ
また、結果の数値間の最大の差がどのようになるかにも注意してください。Δ <= 1/10^p
distribute (0, 7, 100)
=> [ 15, 15, 14, 14, 14, 14, 14 ] // Δ = 1
distribute (1, 7, 100)
=> [ 14.3, 14.3, 14.3, 14.3, 14.3, 14.3, 14.2 ] // Δ = 0.1
distribute (2, 7, 100)
=> [ 14.29, 14.29, 14.29, 14.29, 14.28, 14.28, 14.28 ] // Δ = 0.01
distribute (3, 7, 100)
=> [ 14.286, 14.286, 14.286, 14.286, 14.286, 14.285, 14.285 ] // Δ = 0.001
distribute (4, 7, 100)
=> [ 14.2858, 14.2857, 14.2857, 14.2857, 14.2857, 14.2857, 14.2857 ] // Δ = 0.0001
distribute
意味のある方法で部分的に適用できます。これは、ささいな人々がレストランで請求書を正確に分割するためにそれを使用できる1つの方法です…
// splitTheBill will use precision of 2 which works nice for monies
const splitTheBill = (people, money) =>
distribute (2, people, money)
// partyOfThree splits the bill between 3 people
const partyOfThree = money =>
splitTheBill (3, money)
// how much does each person pay ?
partyOfThree (67.89)
=> [ 18.93, 18.93, 18.92 ]
そして、個人を分割しないように注意しながら、人々をグループに分割する効果的な方法を次に示します。これは通常、死に至ります…
// p=0 will yield only whole numbers in the result
const makeTeams = (teams, people) =>
distribute (0, teams, people)
// make 4 teams from 18 people
// how many people on each team?
makeTeams (4, 18)
=> [ 5, 5, 4, 4 ]
お金について話しているので、通常、合計が正しく加算される限り、数セントの違いは問題になりません。したがって、1回の支払いが残りの支払いよりも数セント高くなる可能性があることを気にしない場合は、分割払いの非常に簡単なソリューションを次に示します.
function CalculateInstallments(total, installments) {
// Calculate Installment Payments
var pennies = total * 100;
var remainder = pennies % installments;
var otherPayments = (pennies - remainder) / installments;
var firstPayment = otherPayments + remainder;
for (var i = 0; i < installments; i++) {
if (i == 0) {
console.log("first payment = ", firstPayment / 100);
} else {
console.log("next payment = ", otherPayments / 100);
}
}
}
最後に最高額の支払いが必要だと言ったので、for ループの if ステートメントを変更します。 if (i==installments-1) { //last payment }
<button onclick="myFunction(3856,3)">Try it</button>
function myFunction(number,divide) {
var money = number / divide;
money = Math.ceil(money * 100) / 100;
alert(money); //1285.34
}