Функция Excel ROUND в Javascript

У меня есть математическая формула в Excel, которая выглядит следующим образом:

ROUND((B2+C2)*(B55/100)/12;2)

Начальные значения:

  • В2 = 1000
  • С2 = 0
  • В55 = 0,03

Результаты (t означает время в месяцах). Функция Excel ROUND в Javascript

Вот мой подход к Javascript:

(function _calculateRates() {
  var singlePayment = parseInt(1000, 10),
    amount = singlePayment,
    monthlyPayment = parseInt(0, 10),
    investTime = parseFloat(12),
    rate_a = parseFloat(0.03),
    rate_b = parseFloat(0.03),
    investment = monthlyPayment,
    interest = 0;

  for (var month = 0; month < investTime; month += 1) {
    investment = (month === 0) ? 0 : monthlyPayment;

    interest = Number(((amount + investment) * (rate_a / 100) / 12).toFixed(2));
    amount = Number((amount + interest + investment).toFixed(2));
  }
  console.info('Result: ', amount);
})();

Как видим, результат неверный.

Где я могу найти алгоритм Microsoft Excel для ROUND()?

Какой результат регистрируется, и какой результат вы хотите вместо этого?

Cat 29.01.2019 09:14

приведите пример одного значения, пожалуйста

Maheer Ali 29.01.2019 09:33

В Excel разделителем аргументов является запятая (,) или точка с запятой (;)? что excel показывает в результате? Должно получиться 2dp...

Solar Mike 29.01.2019 09:37

округление до 2 знаков после запятой... floor((100.0*x)+0.5)*0.01; для разного количества мест вы просто меняете 100 и 0.01 на 10^n и 10^-n

Spektre 29.01.2019 09:41

В Excel=0.3/12 оценивается как 0.025. Итак, округленное до 2 знаков после запятой значение 0.03. В JavaScriptvar result = 0.3/12; приводит к 0.024999999999999998. Этот .toFixed(2) — это 0.02. Вот почему разница.

Axel Richter 29.01.2019 09:44

@AxelRichter 12/3 равно 4, а 3/12 равно 0,25, так почему у javascript такая проблема?

Solar Mike 29.01.2019 10:01

@Solar Mike: Не только JavaScript, но и все системы, использующие Стандарт IEEE для арифметики с плавающей запятой (IEEE 754), будут иметь эту «проблему». Excel дополнительно имеет точность всего 15 цифр максимум. Здесь это выглядит как преимущество, но иногда это не так.

Axel Richter 29.01.2019 10:08

@AxelRichter, так что результат не «точность», а «ошибка» ...

Solar Mike 29.01.2019 10:20

@Solar Mike: Это правильно. Все электронные системы, которые мы используем в настоящее время, нет способны выполнять арифметические операции с плавающей запятой со 100% точностью. Но это так, как есть. Мы должны жить с этим.

Axel Richter 29.01.2019 10:24

@SolarMike проблема в том, что 0,3 не может быть представлено в двоичном виде как точное двоичное число ... это иррационально, поэтому значение немного меньше, чем 0.3, что приводит к немного меньшему результату, чем 0.025, который округляется вниз, поэтому его ошибка округления основана ... на средство, вы можете попробовать это Как бороться с переполнением и недостатком?

Spektre 29.01.2019 13:24

@Spektre: я опубликовал свой ответ в надежде, что кто-то будет возражать против лучшего подхода к округлению JavaScript, чем Math.floor((Math.pow(10, n) * x ) + 0.5) * Math.pow(10, -n). Это действительно громоздко, не так ли?

Axel Richter 29.01.2019 14:05
Поведение ключевого слова "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
11
1 282
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

В Excel =0.3/12 оценивается как 0.025. Итак, округлив до 2 знаков после запятой, получится 0.03.

В JavaScript var result = 0.3/12; приводит к 0.024999999999999998. Этот .toFixed(2) — это 0.02.

Внутренний Excel также получает 0.024999999999999998, как и все системы, использующие Стандарт IEEE для арифметики с плавающей запятой (IEEE 754). Но у него есть дополнительное правило: брать не более 15 цифр. Это 0.02499999999999 + 0.000000000000009, то есть 0.025.

Поэтому мы не можем использовать .toFixed в JavaScript. Если мы используем другой метод округления на JavaScript, то это приводит к тому же результату, что и на Excel.

См. пример с использованием простых значений:

var result = 0.3/12;
console.info(result);
console.info(result.toFixed(2));
console.info(Math.floor((Math.pow(10, 2)*result)+0.5)*Math.pow(10, -2));

См. пример с использованием вашего алгоритма:

(function _calculateRates() {
  var singlePayment = parseInt(1000, 10),
    amount = singlePayment,
    monthlyPayment = parseInt(0, 10),
    investTime = parseFloat(12),
    rate_a = parseFloat(0.03),
    rate_b = parseFloat(0.03),
    investment = monthlyPayment,
    interest = 0;

  for (var month = 0; month < investTime; month += 1) {
    investment = (month === 0) ? 0 : monthlyPayment;

    interest = Number(((amount + investment) * (rate_a / 100) / 12));
    interest = Math.floor((Math.pow(10, 2)*interest)+0.5)*Math.pow(10, -2);
    amount = Number((amount + interest + investment));
    amount = Math.floor((Math.pow(10, 2)*amount)+0.5)*Math.pow(10, -2);
  }
  console.info('Result: ', amount);
})();

Поскольку это связано с этим вопросом, особенно почему в JavaScriptvar result = 0.3/12; приводит к 0.024999999999999998, ссылка на Что должен знать каждый программист об арифметике с плавающей запятой может быть полезной.

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