Какое правило стоит за функцией toFixed () - PullRequest
0 голосов
/ 30 марта 2019

Я тестирую метод toFixed () javascript.Результат показан ниже:

(49.175).toFixed(2) => "49.17"
(49.775).toFixed(2) => "49.77"
(49.185).toFixed(2) => "49.19"
(49.785).toFixed(2) => "49.78"

(49.1175).toFixed(3) => "49.117"
(49.1775).toFixed(3) => "49.178"
(49.1185).toFixed(3) => "49.118"
(49.1785).toFixed(3) => "49.178"

Я провел этот тест в браузере Chrome, и я удивлен результатом.Я не мог уловить логику.Он не подходит ни «округлить от нуля», ни «округлить до четности».Какое правило лежит в основе функции toFixed ()?

Ответы [ 3 ]

2 голосов
/ 30 марта 2019

About toFixed

Возвращает строку, содержащую это числовое значение, представленное в десятичной записи с фиксированной запятой, с дробными цифрами после десятичной запятой.Если FractionDigits не определен, предполагается 0.В частности, выполните следующие шаги:

Алгоритм Number.prototype.toFixed (fractionDigits): https://www.ecma -international.org / ecma-262 / 5.1 / # sec-15.7.4.5

  • Свойство length для метода toFixed равно 1.

    • Если метод toFixed вызывается с более чем одним аргументом, то поведение не определено (см. Раздел 15).

Реализации разрешено расширять поведение toFixed для значений FractionDigits меньше 0 или больше 20. В этом случае toFixed не обязательно выдает RangeError для таких значений.

ПРИМЕЧАНИЕ Вывод toFixed может быть более точным, чем toString для некоторых значений, поскольку toString печатает только достаточно значащие цифры, чтобы отличить число от смежных числовых значений.

JSРабота вокруг

function fix(n, p) {
  return (+(Math.round(+(n + 'e' + p)) + 'e' + -p)).toFixed(p);
}
let exampleA = fix(49.1175, 3);
let exampleB = fix(49.1775, 3);
let exampleC = fix(49.775, 2);
const random = Math.random();
console.log(exampleA);
console.log(exampleB);
console.log(exampleC);
console.log('Before:', random, 'After Custom =>', fix(random, 3), 'Default:', random.toFixed(3));
// 49.118
// 49.178
// 49.78

Требуемая точность

Я предлагаю просто перенести set precision с C ++ на Node.JSМодуль.

  • Вы можете просто подключить и использовать child_process также в Node.JS для вызова программы C ++ с аргументом и иметь C ++ запускает функцию для преобразования значения и вывода в консоль.
1 голос
/ 04 апреля 2019

Проблема в том, что введенные вами цифры не существуют! При сканировании они (двоичные) округляются до ближайшего возможного / существующего числа. toPrecision(18) показывает числа после сканирования более точно:

(49.175).toPrecision(18); // "49.1749999999999972" => "49.17"
(49.775).toPrecision(18); // "49.7749999999999986" => "49.77"
(49.185).toPrecision(18); // "49.1850000000000023" => "49.19"
(49.785).toPrecision(18); // "49.7849999999999966" => "49.78"

Таким образом, число округляется в 2 раза: сначала при сканировании, а затем toFixed().

0 голосов
/ 30 марта 2019

Из MDN :

toFixed() возвращает строковое представление numObj, которое не использует экспоненциальную запись и имеет точно цифры после десятичного разряда.Число является округленным , если необходимо, и дробная часть дополняется нулями, если необходимо, чтобы она имела указанную длину.Если numObj больше или равно 1e + 21, этот метод просто вызывает Number.prototype.toString() и возвращает строку в экспоненциальной записи.

И позже вы можете прочитать:

ПРЕДУПРЕЖДЕНИЕ: Числа с плавающей запятой не могут представлять все десятичные числа точно в двоичном виде, что может привести к неожиданным результатам, таким как 0.1 + 0.2 === 0.3, возвращая false.

Приведенное выше предупреждение в сочетании с логикой округления (возможно, арифметическими операциями над числом) объяснит различные варианты поведения, которые вы экспериментируете в процедуре округления (вы можете прочитать это здесь ).

...