Как сохранить значения веса и преобразовать их в стандартные / метрические веса? - PullRequest
0 голосов
/ 27 мая 2019

Я работаю над приложением Vue, и одна из функций связана со значениями веса. В настоящее время я храню их в своей базе данных в граммах, а затем преобразую их в фунты. В конце концов, я бы хотел, чтобы пользователь мог выбирать между метрическими и стандартными вычислениями. Я создал функцию, которая возвращает четыре вычисления, однако они, похоже, не складываются правильно.

export const convertToPounds = weight => {
  return (Math.round((weight / 453.592) * 10) / 10).toFixed(2);
};

Эта функция запускается четыре раза. Один раз для общего количества и три раза в зависимости от того, к какой категории относятся элементы.

Total - 4170 grams converts to 9.20 lbs
ValueA - 2700 grams converts to 6.00 lbs
ValueB - 1400 grams converts to 3.10 lbs
ValueC - 70 grams converts to 0.20 lbs

Однако, смотря на окончательные преобразования, три значения складываются из 9.30, а не 9.20, которые должны быть возвращены

Мой вопрос заключается в том, является ли метод преобразования слишком неточным для обработки этих типов преобразований? Или хранение весов в граммах не лучший способ справиться с этим сценарием?

Ответы [ 3 ]

1 голос
/ 27 мая 2019

Чтобы добавить комментарий:

Точные числа, такие как 9.20, невозможны.Они двоично округлены до ближайшего возможного числа, здесь до 9.19999999999999929.По этой причине toFixed() возвращает строку, а не число.

Также не помогают функции или выражения, представленные здесь в качестве ответов:

value = Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals);

Если вы подтвердите результат с помощью console.log(value.toPrecision(18)) Вы видите, что функции не работают.Все функции округления, которые возвращают число, потерпят неудачу.

Почему toPrecision(18)?Плавающие числа обычно реализуются как IEEE 754. JavaScript использует double floats с примерно 16 десятичными цифрами.Таким образом, 18 цифр являются очень точным десятичным представлением внутреннего номера.

Конечное примечание: используйте toFixed() только для окончательной печати. ​​

1 голос
/ 27 мая 2019

Я думаю, что ваша проблема в том, что вы сначала округляете его, а затем выполняете toFixed (2), который далее округляет его.Я кратко проверил на Google, и, кажется, правильный расчет: https://www.google.com/search?q=4170+grams+to+pounds

const convertToPounds = weight => {
  return (weight / 453.592).toFixed(2);
};

// Total - 4170 grams converts to 9.20 lbs
console.log(convertToPounds(4170));
// ValueA - 2700 grams converts to 6.00 lbs
console.log(convertToPounds(2700));
// ValueB - 1400 grams converts to 3.10 lbs
console.log(convertToPounds(1400));
// ValueC - 70 grams converts to 0.20 lbs
console.log(convertToPounds(70));
0 голосов
/ 27 мая 2019

Вы округляете. Почему ты округляешь? Неужели пользовательский интерфейс не будет отображать длинный десятичный знак? Если это так, вы должны рассмотреть округление на уровне пользовательского интерфейса. Подобное округление на уровне данных опасно, поскольку, как вы выяснили; все не сложится внутренне, и если вы используете результат этого в другом вычислении , тогда оно будет дрейфовать и становиться более неточным.

Рассмотрим фильтр, чтобы сделать это, как один этот гист (https://gist.github.com/belsrc/672b75d1f89a9a5c192c#file-gistfile1-js-L92):

Vue.filter('round', function(value, decimals) {
  if(!value) {
    value = 0;
  }

  if(!decimals) {
    decimals = 0;
  }

  value = Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals);
  return value;
});
...