注:選択された答えは、好ましくない配列の順序を変更することです。ここでは、同じ結果を達成し、配列の順序を維持する、より多くの異なるバリエーションを提供します
討論
[98.88, .56, .56]
どのように丸めたいですか?4つのオプションがあります
1-切り上げて、残りの数値から加算されたものを引くと、結果は次のようになります。[98, 1, 1]
これは良い答えかもしれませんが、もし私たちが持っているとしたらどう[97.5, .5, .5, .5, .5, .5]
でしょうか?次に、それを切り上げる必要があります[95, 1, 1, 1, 1, 1]
どうなるかわかりますか?0のような数字をさらに追加すると、残りの数字からより多くの価値が失われます。のようなゼロのような数の大きな配列がある場合、これは非常に厄介になる可能性があります[40, .5, .5 , ... , .5]
。これを切り上げると、次のような配列になる可能性があります。[1, 1, .... , 1]
したがって、切り上げは適切なオプションではありません。
2-数値を切り捨てます。したがって、に[98.88, .56, .56]
なり[98, 0, 0]
、100未満の2になります。すでに0であるものはすべて無視し、その差を最大数に合計します。数字が大きいほど多くなります。
3-前と同じですが、数値を切り捨てますが、小数に基づいて降順で並べ替え、小数に基づいて差分を除算します。これにより、最大の小数が差分を取得します。
4-切り上げますが、追加したものを次の数値に追加します。波のように、追加したものは配列の最後にリダイレクトされます。そう[98.88, .56, .56]
なる[99, 0, 1]
これらはどれも理想的ではないため、データの形が崩れることに注意してください。
ここでは、ケース2と3のコードを提供します(ゼロのような数が多い場合、ケースNo.1は実用的ではないため)。それは現代のJsであり、使用するためにライブラリを必要としません
2番目のケース
const v1 = [13.626332, 47.989636, 9.596008, 28.788024];// => [ 14, 48, 9, 29 ]
const v2 = [16.666, 16.666, 16.666, 16.666, 16.666, 16.666] // => [ 17, 17, 17, 17, 16, 16 ]
const v3 = [33.333, 33.333, 33.333] // => [ 34, 33, 33 ]
const v4 = [33.3, 33.3, 33.3, 0.1] // => [ 34, 33, 33, 0 ]
const v5 = [98.88, .56, .56] // =>[ 100, 0, 0 ]
const v6 = [97.5, .5, .5, .5, .5, .5] // => [ 100, 0, 0, 0, 0, 0 ]
const normalizePercentageByNumber = (input) => {
const rounded: number[] = input.map(x => Math.floor(x));
const afterRoundSum = rounded.reduce((pre, curr) => pre + curr, 0);
const countMutableItems = rounded.filter(x => x >=1).length;
const errorRate = 100 - afterRoundSum;
const deductPortion = Math.ceil(errorRate / countMutableItems);
const biggest = [...rounded].sort((a, b) => b - a).slice(0, Math.min(Math.abs(errorRate), countMutableItems));
const result = rounded.map(x => {
const indexOfX = biggest.indexOf(x);
if (indexOfX >= 0) {
x += deductPortion;
console.log(biggest)
biggest.splice(indexOfX, 1);
return x;
}
return x;
});
return result;
}
3番目のケース
const normalizePercentageByDecimal = (input: number[]) => {
const rounded= input.map((x, i) => ({number: Math.floor(x), decimal: x%1, index: i }));
const decimalSorted= [...rounded].sort((a,b)=> b.decimal-a.decimal);
const sum = rounded.reduce((pre, curr)=> pre + curr.number, 0) ;
const error= 100-sum;
for (let i = 0; i < error; i++) {
const element = decimalSorted[i];
element.number++;
}
const result= [...decimalSorted].sort((a,b)=> a.index-b.index);
return result.map(x=> x.number);
}
4番目のケース
各ラウンドアップで数値に追加または差し引かれる余分な空気の量を計算し、次の項目で再度加算または減算する必要があります。
const v1 = [13.626332, 47.989636, 9.596008, 28.788024];// => [14, 48, 10, 28 ]
const v2 = [16.666, 16.666, 16.666, 16.666, 16.666, 16.666] // => [17, 16, 17, 16, 17, 17]
const v3 = [33.333, 33.333, 33.333] // => [33, 34, 33]
const v4 = [33.3, 33.3, 33.3, 0.1] // => [33, 34, 33, 0]
const normalizePercentageByWave= v4.reduce((pre, curr, i, arr) => {
let number = Math.round(curr + pre.decimal);
let total = pre.total + number;
const decimal = curr - number;
if (i == arr.length - 1 && total < 100) {
const diff = 100 - total;
total += diff;
number += diff;
}
return { total, numbers: [...pre.numbers, number], decimal };
}, { total: 0, numbers: [], decimal: 0 });