Форматирование числа с точностью до двух десятичных знаков в JavaScript

У меня есть эта строка кода, которая округляет мои числа до двух десятичных знаков. Но я получаю такие числа: 10,8, 2,4 и т. Д. Это не мое представление о двух десятичных знаках, так как я могу улучшить следующее?

Math.round(price*Math.pow(10,2))/Math.pow(10,2);

Я хочу цифры как 10.80, 2.40 и т. Д. Использование JQuery хорошо для меня.

34 ответа

Решение

Чтобы отформатировать число с помощью записи с фиксированной запятой, вы можете просто использовать метод toFixed:

(10.8).toFixed(2); // "10.80"

var num = 2.4;
alert(num.toFixed(2)); // "2.40"

Обратите внимание, что toFixed() возвращает строку

ВАЖНО: обратите внимание, что toFixed на самом деле не округляется, 90% времени, он возвращает округленное значение, но во многих случаях он на самом деле не работает. Попробуйте это в вашей консоли:

2.005.toFixed(2)

Вы получите неправильный ответ

Не существует естественного способа получить десятичное округление в javascript, вам понадобится ваш собственный polyfill или использовать библиотеку. Вы можете посмотреть на polyfill Mozilla для этого https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round

Это старая тема, но она по-прежнему занимает первое место в результатах поиска Google, и предлагаемые решения имеют ту же проблему с десятичной запятой с плавающей запятой. Вот (очень общая) функция, которую я использую, благодаря MDN:

function round(value, exp) {
  if (typeof exp === 'undefined' || +exp === 0)
    return Math.round(value);

  value = +value;
  exp = +exp;

  if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));

  // Shift back
  value = value.toString().split('e');
  return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
}

Как мы видим, мы не получаем эти проблемы:

round(1.275, 2);   // Returns 1.28
round(1.27499, 2); // Returns 1.27

Эта универсальность также предоставляет некоторые интересные вещи:

round(1234.5678, -2);   // Returns 1200
round(1.2345678e+2, 2); // Returns 123.46
round("123.45");        // Returns 123

Теперь, чтобы ответить на вопрос ОП, нужно набрать:

round(10.8034, 2).toFixed(2); // Returns "10.80"
round(10.8, 2).toFixed(2);    // Returns "10.80"

Или, для более краткой, менее общей функции:

function round2Fixed(value) {
  value = +value;

  if (isNaN(value))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + 2) : 2)));

  // Shift back
  value = value.toString().split('e');
  return (+(value[0] + 'e' + (value[1] ? (+value[1] - 2) : -2))).toFixed(2);
}

Вы можете позвонить с помощью:

round2Fixed(10.8034); // Returns "10.80"
round2Fixed(10.8);    // Returns "10.80"

Различные примеры и тесты (спасибо T.J. Crowder!):

function round(value, exp) {
  if (typeof exp === 'undefined' || +exp === 0)
    return Math.round(value);

  value = +value;
  exp = +exp;

  if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));

  // Shift back
  value = value.toString().split('e');
  return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
}
function naive(value, exp) {
  if (!exp) {
    return Math.round(value);
  }
  var pow = Math.pow(10, exp);
  return Math.round(value * pow) / pow;
}
function test(val, places) {
  subtest(val, places);
  val = typeof val === "string" ? "-" + val : -val;
  subtest(val, places);
}
function subtest(val, places) {
  var placesOrZero = places || 0;
  var naiveResult = naive(val, places);
  var roundResult = round(val, places);
  if (placesOrZero >= 0) {
    naiveResult = naiveResult.toFixed(placesOrZero);
    roundResult = roundResult.toFixed(placesOrZero);
  } else {
    naiveResult = naiveResult.toString();
    roundResult = roundResult.toString();
  }
  $("<tr>")
    .append($("<td>").text(JSON.stringify(val)))
    .append($("<td>").text(placesOrZero))
    .append($("<td>").text(naiveResult))
    .append($("<td>").text(roundResult))
    .appendTo("#results");
}
test(0.565, 2);
test(0.575, 2);
test(0.585, 2);
test(1.275, 2);
test(1.27499, 2);
test(1234.5678, -2);
test(1.2345678e+2, 2);
test("123.45");
test(10.8034, 2);
test(10.8, 2);
test(1.005, 2);
test(1.0005, 2);
table {
  border-collapse: collapse;
}
table, td, th {
  border: 1px solid #ddd;
}
td, th {
  padding: 4px;
}
th {
  font-weight: normal;
  font-family: sans-serif;
}
td {
  font-family: monospace;
}
<table>
  <thead>
    <tr>
      <th>Input</th>
      <th>Places</th>
      <th>Naive</th>
      <th>Thorough</th>
    </tr>
  </thead>
  <tbody id="results">
  </tbody>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Я обычно добавляю это в свою личную библиотеку, и после некоторых предложений и использования решения @TIMINeutron, а затем, делая его адаптируемым для десятичной длины, этот вариант подходит лучше всего:

function precise_round(num, decimals) {
   var t = Math.pow(10, decimals);   
   return (Math.round((num * t) + (decimals>0?1:0)*(Math.sign(num) * (10 / Math.pow(100, decimals)))) / t).toFixed(decimals);
}

будет работать для зарегистрированных исключений.

БЫСТРО И ЛЕГКО

      parseFloat(number.toFixed(2))

Пример

      let number = 2.55435930

let roundedString = number.toFixed(2)    // "2.55"

let twoDecimalsNumber = parseFloat(roundedString)    // 2.55

let directly = parseFloat(number.toFixed(2))    // 2.55

Один из способов на 100% быть уверенным, что вы получите число с двумя десятичными знаками:

(Math.round(num*100)/100).toFixed(2)

Если это вызывает ошибки округления, вы можете использовать следующее, как объяснил Джеймс в своем комментарии:

(Math.round((num * 1000)/10)/100).toFixed(2)

Я не знаю, почему я не могу добавить комментарий к предыдущему ответу (возможно, я безнадежно слеп, не знаю), но я нашел решение, используя ответ @Miguel:

function precise_round(num,decimals) {
   return Math.round(num*Math.pow(10, decimals)) / Math.pow(10, decimals);
}

И два комментария (от @bighostkim и @Imre):

  • Проблема с precise_round(1.275,2) не возвращается 1.28
  • Проблема с precise_round(6,2) не возвращая 6.00 (как он хотел).

Мое окончательное решение заключается в следующем:

function precise_round(num,decimals) {
    var sign = num >= 0 ? 1 : -1;
    return (Math.round((num*Math.pow(10,decimals)) + (sign*0.001)) / Math.pow(10,decimals)).toFixed(decimals);
}

Как вы видите, мне пришлось добавить немного "исправления" (это не то, что есть, но поскольку Math.round с потерями - вы можете проверить это на jsfiddle.net - это единственный способ, который я знал, как "исправить" " Это). Он добавляет 0,001 к уже дополненному номеру, поэтому он добавляет 1 три 0s справа от десятичного значения. Так что это должно быть безопасно для использования.

После этого я добавил .toFixed(decimal) всегда выводить число в правильном формате (с правильным количеством десятичных знаков).

Вот и все. Используйте это хорошо;)

РЕДАКТИРОВАТЬ: добавлен функционал для "коррекции" отрицательных чисел.

toFixed(n) предоставляет n длины после десятичной точки; toPrecision(x) обеспечивает x общую длину.

Используйте этот метод ниже

// Example: toPrecision(4) when the number has 7 digits (3 before, 4 after)
    // It will round to the tenths place
    num = 500.2349;
    result = num.toPrecision(4); // result will equal 500.2

И если вы хотите, чтобы номер был фиксированным, используйте

result = num.toFixed(2);

Я не нашел точного решения этой проблемы, поэтому я создал свое собственное:

function inprecise_round(value, decPlaces) {
  return Math.round(value*Math.pow(10,decPlaces))/Math.pow(10,decPlaces);
}

function precise_round(value, decPlaces){
    var val = value * Math.pow(10, decPlaces);
    var fraction = (Math.round((val-parseInt(val))*10)/10);

    //this line is for consistency with .NET Decimal.Round behavior
    // -342.055 => -342.06
    if(fraction == -0.5) fraction = -0.6;

    val = Math.round(parseInt(val) + fraction) / Math.pow(10, decPlaces);
    return val;
}

Примеры:

function inprecise_round(value, decPlaces) {
  return Math.round(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}

function precise_round(value, decPlaces) {
  var val = value * Math.pow(10, decPlaces);
  var fraction = (Math.round((val - parseInt(val)) * 10) / 10);

  //this line is for consistency with .NET Decimal.Round behavior
  // -342.055 => -342.06
  if (fraction == -0.5) fraction = -0.6;

  val = Math.round(parseInt(val) + fraction) / Math.pow(10, decPlaces);
  return val;
}

// This may produce different results depending on the browser environment
console.log("342.055.toFixed(2)         :", 342.055.toFixed(2)); // 342.06 on Chrome & IE10

console.log("inprecise_round(342.055, 2):", inprecise_round(342.055, 2)); // 342.05
console.log("precise_round(342.055, 2)  :", precise_round(342.055, 2));   // 342.06
console.log("precise_round(-342.055, 2) :", precise_round(-342.055, 2));  // -342.06

console.log("inprecise_round(0.565, 2)  :", inprecise_round(0.565, 2));   // 0.56
console.log("precise_round(0.565, 2)    :", precise_round(0.565, 2));     // 0.57

Округлить вниз

function round_down(value, decPlaces) {
    return Math.floor(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}

Округлять

function round_up(value, decPlaces) {
    return Math.ceil(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}

Ближайший тур

function round_nearest(value, decPlaces) {
    return Math.round(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}

Объединенные /questions/5356169/kak-ya-mogu-udalit-desyatichnuyu-chast-iz-chisla-javascript/5356180#5356180 и https://www.kirupa.com/html5/rounding_numbers_in_javascript.htm Спасибо им.

Вот простой

function roundFloat(num,dec){
    var d = 1;
    for (var i=0; i<dec; i++){
        d += "0";
    }
    return Math.round(num * d) / d;
}

Используйте как alert(roundFloat(1.79209243929,4));

Jsfiddle

Основываясь на ответе Кристиана С. Сальвадо , выполнение следующих действий приведет к выводу типа, а также, похоже, хорошо справляется с округлением:

      const roundNumberToTwoDecimalPlaces = (num) => Number(new Intl.NumberFormat('en-US', {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2,
}).format(num));

roundNumberToTwoDecimalPlaces(1.344); // => 1.34
roundNumberToTwoDecimalPlaces(1.345); // => 1.35

Разница между вышеупомянутым и уже упомянутым состоит в том, что вам не нужен .format() цепочки, когда вы его используете [, и что он выводит Number тип].

@heridev и я создали небольшую функцию в jQuery.

Вы можете попробовать следующее:

HTML

<input type="text" name="one" class="two-digits"><br>
<input type="text" name="two" class="two-digits">​

JQuery

// apply the two-digits behaviour to elements with 'two-digits' as their class
$( function() {
    $('.two-digits').keyup(function(){
        if($(this).val().indexOf('.')!=-1){         
            if($(this).val().split(".")[1].length > 2){                
                if( isNaN( parseFloat( this.value ) ) ) return;
                this.value = parseFloat(this.value).toFixed(2);
            }  
         }            
         return this; //for chaining
    });
});

ДЕМО ОНЛАЙН:

http://jsfiddle.net/c4Wqn/

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

Когда компьютер хранит 1,275 в качестве значения с плавающей запятой, он фактически не будет помнить, было ли это 1,275 или 1,27499999999999993, или даже 1,27500000000000002. Эти значения должны давать разные результаты после округления до двух десятичных знаков, но они не будут, поскольку для компьютера они выглядят одинаково после сохранения в виде значений с плавающей запятой, и нет никакого способа восстановить потерянные данные. Любые дальнейшие вычисления только накапливают такую ​​неточность.

Так что, если точность имеет значение, вы должны избегать значений с плавающей точкой с самого начала. Самые простые варианты

  • использовать выделенную библиотеку
  • использовать строки для хранения и передачи значений (сопровождается строковыми операциями)
  • используйте целые числа (например, вы можете передавать сумму, равную сотым от вашей действительной стоимости, например, сумма в центах вместо суммы в долларах)

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

function descale(num, decimals) {
    var hasMinus = num < 0;
    var numString = Math.abs(num).toString();
    var precedingZeroes = '';
    for (var i = numString.length; i <= decimals; i++) {
        precedingZeroes += '0';
    }
    numString = precedingZeroes + numString;
    return (hasMinus ? '-' : '') 
        + numString.substr(0, numString.length-decimals) 
        + '.' 
        + numString.substr(numString.length-decimals);
}

alert(descale(127, 2));

Со строками вам понадобится округление, но оно все еще управляемо:

function precise_round(num, decimals) {
    var parts = num.split('.');
    var hasMinus = parts.length > 0 && parts[0].length > 0 && parts[0].charAt(0) == '-';
    var integralPart = parts.length == 0 ? '0' : (hasMinus ? parts[0].substr(1) : parts[0]);
    var decimalPart = parts.length > 1 ? parts[1] : '';
    if (decimalPart.length > decimals) {
        var roundOffNumber = decimalPart.charAt(decimals);
        decimalPart = decimalPart.substr(0, decimals);
        if ('56789'.indexOf(roundOffNumber) > -1) {
            var numbers = integralPart + decimalPart;
            var i = numbers.length;
            var trailingZeroes = '';
            var justOneAndTrailingZeroes = true;
            do {
                i--;
                var roundedNumber = '1234567890'.charAt(parseInt(numbers.charAt(i)));
                if (roundedNumber === '0') {
                    trailingZeroes += '0';
                } else {
                    numbers = numbers.substr(0, i) + roundedNumber + trailingZeroes;
                    justOneAndTrailingZeroes = false;
                    break;
                }
            } while (i > 0);
            if (justOneAndTrailingZeroes) {
                numbers = '1' + trailingZeroes;
            }
            integralPart = numbers.substr(0, numbers.length - decimals);
            decimalPart = numbers.substr(numbers.length - decimals);
        }
    } else {
        for (var i = decimalPart.length; i < decimals; i++) {
            decimalPart += '0';
        }
    }
    return (hasMinus ? '-' : '') + integralPart + (decimals > 0 ? '.' + decimalPart : '');
}

alert(precise_round('1.275', 2));
alert(precise_round('1.27499999999999993', 2));

Обратите внимание, что эта функция округляет до ближайшего, связывает от нуля, в то время как IEEE 754 рекомендует округлять до ближайшего, даже в качестве поведения по умолчанию для операций с плавающей запятой. Такие модификации оставлены в качестве упражнения для читателя:)

/**
 * MidpointRounding away from zero ('arithmetic' rounding)
 * Uses a half-epsilon for correction. (This offsets IEEE-754
 * half-to-even rounding that was applied at the edge cases).
 */

function RoundCorrect(num, precision = 2) {
 // half epsilon to correct edge cases.
 var c = 0.5 * Number.EPSILON * num;
// var p = Math.pow(10, precision); //slow
 var p = 1; while (precision--> 0) p *= 10;
 if (num < 0)
  p *= -1;
 return Math.round((num + c) * p) / p;
}

// testing some +ve edge cases
console.log(RoundCorrect(1.005, 2));  // 1.01 correct
console.log(RoundCorrect(2.175, 2));  // 2.18 correct
console.log(RoundCorrect(5.015, 2));  // 5.02 correct

// testing some -ve edge cases
console.log(RoundCorrect(-1.005, 2));  // -1.01 correct
console.log(RoundCorrect(-2.175, 2));  // -2.18 correct
console.log(RoundCorrect(-5.015, 2));  // -5.02 correct

Number(Math.round(1.005+'e2')+'e-2'); // 1.01

Это сработало для меня: округление десятичных дробей в JavaScript

В этих примерах вы все равно получите ошибку при попытке округлить число 1.005, решение состоит в том, чтобы использовать библиотеку, такую ​​как Math.js, или эту функцию:

function round(value: number, decimals: number) {
    return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
}

Округлите свое десятичное значение, затем используйте toFixed(x) для ожидаемой цифры (й).

function parseDecimalRoundAndFixed(num,dec){
  var d =  Math.pow(10,dec);
  return (Math.round(num * d) / d).toFixed(dec);
}

Вызов

parseDecimalRoundAndFixed(10.800243929,4) => 10.80 parseDecimalRoundAndFixed(10.807243929,2) => 10.81

Вот мое 1-строчное решение: Number((yourNumericValueHere).toFixed(2));

Вот что происходит:

1) Сначала вы подаете заявку.toFixed(2)на число, которое вы хотите округлить десятичных знаков. Обратите внимание, что это преобразует значение в строку из числа. Так что, если вы используете Typescript, он выдаст такую ​​ошибку:

"Тип 'строка' не может быть назначен типу 'число'"

2) Чтобы вернуть числовое значение или преобразовать строку в числовое значение, просто применитеNumber()функция на этом так называемом "строковом" значении.

Для уточнения посмотрите на пример ниже:

ПРИМЕР: у меня есть количество, которое имеет до 5 цифр в десятичных разрядах, и я хотел бы сократить его до 2 десятичных разрядов. Я делаю это так:

var price = 0.26453;
var priceRounded = Number((price).toFixed(2));
console.log('Original Price: ' + price);
console.log('Price Rounded: ' + priceRounded);

Number(((Math.random() * 100) + 1).toFixed(2))

это вернет случайное число от 1 до 100, округленное до 2 десятичных знаков.

parse = function (data) {
       data = Math.round(data*Math.pow(10,2))/Math.pow(10,2);
       if (data != null) {
            var lastone = data.toString().split('').pop();
            if (lastone != '.') {
                 data = parseFloat(data);
            }
       }
       return data;
  };

$('#result').html(parse(200)); // output 200
$('#result1').html(parse(200.1)); // output 200.1
$('#result2').html(parse(200.10)); // output 200.1
$('#result3').html(parse(200.109)); // output 200.11
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="result"></div>
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>

Я получил некоторые идеи из этого поста несколько месяцев назад, но ни один из ответов здесь, ни ответы из других постов / блогов не могли обработать все сценарии (например, отрицательные числа и некоторые "счастливые числа", найденные нашим тестировщиком). В итоге наш тестер не нашел никаких проблем с этим методом ниже. Вставка фрагмента моего кода:

fixPrecision: function (value) {
    var me = this,
        nan = isNaN(value),
        precision = me.decimalPrecision;

    if (nan || !value) {
        return nan ? '' : value;
    } else if (!me.allowDecimals || precision <= 0) {
        precision = 0;
    }

    //[1]
    //return parseFloat(Ext.Number.toFixed(parseFloat(value), precision));
    precision = precision || 0;
    var negMultiplier = value < 0 ? -1 : 1;

    //[2]
    var numWithExp = parseFloat(value + "e" + precision);
    var roundedNum = parseFloat(Math.round(Math.abs(numWithExp)) + 'e-' + precision) * negMultiplier;
    return parseFloat(roundedNum.toFixed(precision));
},

У меня также есть комментарии к коду (извините, я уже забыл все детали)... Я публикую свой ответ здесь для дальнейшего использования:

9.995 * 100 = 999.4999999999999
Whereas 9.995e2 = 999.5
This discrepancy causes Math.round(9.995 * 100) = 999 instead of 1000.
Use e notation instead of multiplying /dividing by Math.Pow(10,precision).

Поместите следующее в какую-то глобальную область:

Number.prototype.getDecimals = function ( decDigCount ) {
   return this.toFixed(decDigCount);
}

а затем попробуйте:

var a = 56.23232323;
a.getDecimals(2); // will return 56.23

Обновить

Обратите внимание, что toFixed() может работать только для числа десятичных знаков между 0-20 т.е. a.getDecimals(25) может вызвать ошибку javascript, поэтому вы можете добавить дополнительную проверку, т.е.

Number.prototype.getDecimals = function ( decDigCount ) {
   return ( decDigCount > 20 ) ? this : this.toFixed(decDigCount);
}

Используя этот ответ по ссылке: /questions/36768445/formatirovanie-chisla-s-tochnostyu-do-dvuh-desyatichnyih-znakov-v-javascript/36768452#36768452

Я строю функцию, чтобы получить динамические числа десятичных дробей:

function toDec(num, dec)
{
        if(typeof dec=='undefined' || dec<0)
                dec = 2;

        var tmp = dec + 1;
        for(var i=1; i<=tmp; i++)
                num = num * 10;

        num = num / 10;
        num = Math.round(num);
        for(var i=1; i<=dec; i++)
                num = num / 10;

        num = num.toFixed(dec);

        return num;
}

Вот рабочий пример: https://jsfiddle.net/wpxLduLc/

(Math.round((10.2)*100)/100).toFixed(2)

Это должно дать: 10.20

(Math.round((.05)*100)/100).toFixed(2)

Это должно дать: 0.05

(Math.round((4.04)*100)/100).toFixed(2)

Это должно дать: 4.04

и т.п.

Вы также можете использовать .toPrecision() метод и некоторый пользовательский код, и всегда округлять до n-й десятичной цифры независимо от длины части int.

function glbfrmt (number, decimals, seperator) {
    return typeof number !== 'number' ? number : number.toPrecision( number.toString().split(seperator)[0].length + decimals);
}

Вы также можете сделать его плагином для лучшего использования.

Просто как это.

var rounded_value=Math.round(value * 100) / 100;
      fun Any.twoDecimalPlaces(numInDouble: Double): String {

    return "%.2f".format(numInDouble)
}

Я исправил проблему модификатором. Поддержка 2 десятичных только.

$(function(){
  //input number only.
  convertNumberFloatZero(22); // output : 22.00
  convertNumberFloatZero(22.5); // output : 22.50
  convertNumberFloatZero(22.55); // output : 22.55
  convertNumberFloatZero(22.556); // output : 22.56
  convertNumberFloatZero(22.555); // output : 22.55
  convertNumberFloatZero(22.5541); // output : 22.54
  convertNumberFloatZero(22222.5541); // output : 22,222.54

  function convertNumberFloatZero(number){
 if(!$.isNumeric(number)){
  return 'NaN';
 }
 var numberFloat = number.toFixed(3);
 var splitNumber = numberFloat.split(".");
 var cNumberFloat = number.toFixed(2);
 var cNsplitNumber = cNumberFloat.split(".");
 var lastChar = splitNumber[1].substr(splitNumber[1].length - 1);
 if(lastChar > 0 && lastChar < 5){
  cNsplitNumber[1]--;
 }
 return Number(splitNumber[0]).toLocaleString('en').concat('.').concat(cNsplitNumber[1]);
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

Вот реализация на TypeScript /questions/36768445/formatirovanie-chisla-s-tochnostyu-do-dvuh-desyatichnyih-znakov-v-javascript/36768470#36768470. Он также упрощает работу с функциями и допускает дополнительное смещение цифр.

export function round(rawValue: number | string, precision = 0, fractionDigitOffset = 0): number | string {
  const value = Number(rawValue);
  if (isNaN(value)) return rawValue;

  precision = Number(precision);
  if (precision % 1 !== 0) return NaN;

  let [ stringValue, exponent ] = scientificNotationToParts(value);

  let shiftExponent = exponentForPrecision(exponent, precision, Shift.Right);
  const enlargedValue = toScientificNotation(stringValue, shiftExponent);
  const roundedValue = Math.round(enlargedValue);

  [ stringValue, exponent ] = scientificNotationToParts(roundedValue);
  const precisionWithOffset = precision + fractionDigitOffset;
  shiftExponent = exponentForPrecision(exponent, precisionWithOffset, Shift.Left);

  return toScientificNotation(stringValue, shiftExponent);
}

enum Shift {
  Left = -1,
  Right = 1,
}

function scientificNotationToParts(value: number): Array<string> {
  const [ stringValue, exponent ] = value.toString().split('e');
  return [ stringValue, exponent ];
}

function exponentForPrecision(exponent: string, precision: number, shift: Shift): number {
  precision = shift * precision;
  return exponent ? (Number(exponent) + precision) : precision;
}

function toScientificNotation(value: string, exponent: number): number {
  return Number(`${value}e${exponent}`);
}

Ни один из примеров не может правильно округлить это:

var x= 0,06 * 3,75; //0.22499999999999998

Все вышеперечисленные решения возвращают 0,22, тогда как должно быть 0,23!

И когда некоторые примерные функции возвращают значение правильно, они возвращают неверное значение для раунда для значения 3,345!

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