Как сохранить значения веса и преобразовать их в стандартные/метрические веса?

Я работаю над приложением 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, которые должны быть возвращены.

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

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
72
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

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

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

// Total - 4170 grams converts to 9.20 lbs
console.info(convertToPounds(4170));
// ValueA - 2700 grams converts to 6.00 lbs
console.info(convertToPounds(2700));
// ValueB - 1400 grams converts to 3.10 lbs
console.info(convertToPounds(1400));
// ValueC - 70 grams converts to 0.20 lbs
console.info(convertToPounds(70));

Я верю, что это исправляет это, спасибо! Вот где действительно проявляется мой нубский javascript, должно быть очевидно, что виновником был Math.round. Я думаю, что нашел эту функцию где-то некоторое время назад, и в то время она, казалось, работала, пока я действительно не начал ее использовать. Спасибо еще раз!

J. Jackson 27.05.2019 15:21

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

Рассмотрим фильтр для этого, например, этот (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;
});

Да, именно поэтому я округляю. Попробую фильтр, спасибо!

J. Jackson 27.05.2019 15:18

Для длинного комментария:

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

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

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

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

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

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

Интересно, это часть математики/javascript/как бы вы это ни называли, с которой я просто очень не знаком. Почему, однако, имеет значение, делаю ли я toFixed() во время расчета или внутри пользовательского интерфейса? Похоже, это приведет к той же проблеме.

J. Jackson 27.05.2019 15:17

Другие вопросы по теме