Почему следующая функция округления не округляет некоторые числовые значения? [Дубликат]

1

Это функция:

export const round = (value, precision) => {
  const multiplier = Math.pow(10, precision || 0)
  return Math.round(value * multiplier) / multiplier
}

Когда я использую round в этой функции:

SET_CAMERA_ZOOM (state, number = 0) {
  // the default is 1.4
  const cameraZoom = state.markerEditor.cameraZoom
  const roundedCameraZoom = round(cameraZoom, 1)
  state.markerEditor.cameraZoom = roundedCameraZoom + number
}

Я получаю, когда число равно 0.4:

1.4
1.7999999999999998
1.8
2.2
2.6
3

И когда число -0.4 (и начиная с 3):

2.6
2.2
1.8000000000000003
1.8
1.4
0.9999999999999999

Почему я получаю эти неосвещенные номера и как изменять round поэтому вместо 1.8 и 1?

ОБНОВЛЕНИЕ: Я пробовал решения из других ссылок. Как этот:

precision = precision || 0
return parseFloat(parseFloat(number).toFixed(precision))

Я все еще получаю такие вещи, как: 0.9999999999999999.

  • 0
    Много вопросов по округлению. ToFixed делает работу?
  • 0
    Это то, что функция должна делать? state.markerEditor.cameraZoom = round( state.markerEditor.cameraZoom + number, 1);
Показать ещё 9 комментариев
Теги:
math

2 ответа

4
Лучший ответ

Причина, по которой вы получаете номера, такие как 1.7999999999999998 с ограниченной точностью номеров javascript (см. 1.7999999999999998 плавающей запятой?)

Поэтому, когда вы делаете что-то с фракциями, вы получаете такие результаты, как:

function round (value, precision) {
  var multiplier = Math.pow(10, precision || 0);
  return Math.round(value * multiplier) / multiplier
}

for (var i=1, x=-.4; i<5; i++) console.log(round(x*i, 1) + 1);

Округление работает, но как только вы делаете больше арифметики (т.е. + 1), вы возвращаетесь к проблеме с ограниченной точностью.

Это намного лучше применить к последнему шагу, поэтому вы сохраняете точность во время операций и только теряете ее в конце, сохраняя округление, например

// Do arithmetic, then round as very last operation
for (var i=1, x=-.4; i<5; i++) console.log(Number((x * i + 1).toFixed(1)));

Использование Number(...) преобразуется в число в конце, чтобы показать точность и округление.

  • 0
    «Гораздо лучше применять Math.round в качестве последнего шага» Извините, но где правильный код? Я не могу найти это в вашем ответе. (Я не очень уверен, как применить ваш код к моей функции округления).
  • 0
    Извините, это должно было быть исправлено . Обновлено.
3

Вероятно, проблема связана с вашим последним утверждением

return Math.round(value * multiplier) / multiplier

вы, вероятно,

return Math.round((value * multiplier) / multiplier)

или вы хотите это

return Math.round(value * 10 ) / 10 // multiply by 10, round , divide
//by 10

Вы делите на число, которое в javascript отличается от целого, поэтому, если вы не округлите полное значение, вы, вероятно, не получите целое число. В Java, если вы выполняете целочисленное деление, он автоматически обрезает значение, приводящее к потере точности, но javaScript не является Java, поэтому для получения желаемого поведения вам нужно округлить в нужном месте или использовать умножить, а затем разделить поведение на усечение значений. Вот ссылка, которая поможет вам понять различия между арифметическими операциями Java и javaScript. Https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators

  • 0
    Я все еще получаю 1.7999999999999998 и 1.8000000000000003 .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню