Думаю всі програмісти зіткалися з проблемою, коли потрібно округлити нескінченне число до потрібної кількості знаків після крапки. Тут є декілька варіантів, і ви можете обрати потрібний, виходячи з ваших потреб.
Ліпший варіант, це спочатку помножити число на кількість знаків, і після поділити:
const to8Ceil = (val) => {
if (!val) return 0
const num = parseFloat(val)
return Math.ceil(num * 100000000) / 100000000
}
const nm = 0.123456789
// to8Ceil(nm) -- 0.12345679
Цей код як бачите округляє до більшого значення, якщо ж вам потрібно округлити до меншого, то замість Math.ceil
, ви можете використати Math.floor
.
Як зберігати точні данні?
Але звідси ви можете зіткнутися з проблемою, коли вам потрібно показати користувачу одне число, наприклад в полі, але це число може вираховувати інші точні данні, і в такому випадку обраховуючи округлене число, ви зіткнетеся з проблемою, що фінальний результат буде невірним.
Наприклад:
- Вам треба порахувати вартість однієї валюти до іншої.
- Курс 0.33123123123.
- В першому полі, пускай USD - у вас 725
- Ви рахуєте 0.33123123123 * 725 = 240.142642642
- Припустимо вам треба округлити до 5 знаків to5Ceil
- to5Ceil(240.142642642) = 240.14265
Наче все добре, у користувача в полі 2 буде невірне для обислення значення. Тому що 240.14265 / 0.33123123123 != 725, а буде дорівнювати 725.000022215. Це сталося через те, що ви округлене число приняли як істину, тому вам доведеться зберігати 2 варінти. Тобто замість змінної, ви зберігаєте обʼєкт, в якому у вас буде: точне значення, реактивне округлене значення (toCeil), та id за необхідністю.
const obj = {
amount: 0.33213123123,
id: "field_1"
get ceilAmount() {
return Math.ceil(this.amount * 1000) / 1000;
}
}
console.log(obj.ceilAmount); // 0.333
Таким чином коли вам буде потрібно взаємодіяти з полями, ви використовуєте як значення поля обʼєкт з певним id, та його внутрішню змінну amount, як змінну для вираховування логіки. Але в саме значення поля ви виводите ceilAmount, що візуально виводить користувачу округлену сумму, але вираховування йде по точному значенню.
Але тут може бути і інша проблема - якщо користувач захоче змінити поле 2, де зараз введено округлене число, то фактично воно стане істиним, і в поле 1 буде повернуте не корректне значення. Нажаль тут нема корректного рішення.
Ви звістно можете зберігати в обʼєкт більше данних, та вираховувати різницію коофіцієнту, але все одно, коли потіи користувач змінить поле 1, то вам доведеться попадати ще в більші граблі. Тому я би рекомендував залишити це як данність, тому що навіть криптокалькулятори всі, на це забивають... І все працює в одностороньому порядку.