Обрізати число до двох десяткових знаків без округлення


196

Припустимо, у мене є значення 15,7784514, я хочу відобразити його 15,77 без округлення.

var num = parseFloat(15.7784514);
document.write(num.toFixed(1)+"<br />");
document.write(num.toFixed(2)+"<br />");
document.write(num.toFixed(3)+"<br />");
document.write(num.toFixed(10));

Призводить до -

15.8
15.78
15.778
15.7784514000 

Як відображати 15,77?


3
Мені спокуса запитати, чому ви не хочете округлення? Здається, неправильно, де б не було ...
Каміло Мартін

39
Це корисно при відображенні валюти.
Річард Єв

@ mik01aj - Коли відображається валюта, частіше обрізати обчислені значення, а не округляти їх. Наприклад, більшість податкових форм у США скорочуються, а не круглі обчислені дробові центи. У цьому випадку усічене значення - це правильне значення.
Стівен Байкс

4
@CamiloMartin існує велика різниця між боргом у 1,49 мільярда доларів та 1,0 мільярда доларів.
Брода Ноель

3
Існує також величезна різниця між 1,49 мільярда і 1,50 мільярда доларів. Це 100 мільйонів доларів.
Ліга

Відповіді:


228

Перетворіть число в рядок, порівняйте число до другого десяткового місця:

function calc(theform) {
    var num = theform.original.value, rounded = theform.rounded
    var with2Decimals = num.toString().match(/^-?\d+(?:\.\d{0,2})?/)[0]
    rounded.value = with2Decimals
}
<form onsubmit="return calc(this)">
Original number: <input name="original" type="text" onkeyup="calc(form)" onchange="calc(form)" />
<br />"Rounded" number: <input name="rounded" type="text" placeholder="readonly" readonly>
</form>

toFixedМетод зазнає невдачі в деяких випадках в відміну toString, так що будьте дуже обережні з ним.


22
+1 Це повинно вирішити питання округлення. Я б до сих пір виводить результат вище використання toFixed, хоча, так: (Math.floor(value * 100) / 100).toFixed(2). Як ви, мабуть, знаєте, дивні речі точності можуть траплятися зі значеннями з плаваючою точкою (а з іншого боку спектру, якщо число трапляється 15, звучить так, як хоче ОП 15.00).
TJ Crowder

1
хе-хе, або якщо ви поєднаєте обидва:Number((15.7784514000*100).toString().match(/^\d+/)/100);
skobaljic

27
Math.floor (значення * 100) / 100 не працюватиме, якщо значення = 4,27 серйозно, спробуйте.
Темний Бегемот

3
@DarkHippo Thats тому, що 4.27 - це фактично 4.26999999999, Math.round - це, як правило, краще рішення, хоч і не відповідь на початкове запитання. Реально заданий вихідний рядок - це рядок, це слід робити за допомогою маніпуляції з рядком замість числового рішення з усіма дисками з плаваючою комою.
БЮР

3
... це не звучить правильно. Перетворення між типами за будь-яких обставин здається круглим та небезпечним. Якщо тільки справді просунутий програміст не стверджує, що "всі типи - це просто потоки" чи щось таке.
JackHasaKeyboard

66

Оновлення 5 листопада 2016 року

Нова відповідь, завжди точна

function toFixed(num, fixed) {
    var re = new RegExp('^-?\\d+(?:\.\\d{0,' + (fixed || -1) + '})?');
    return num.toString().match(re)[0];
}

Оскільки математика з плаваючою комою у JavaScript завжди матиме крайові випадки, попереднє рішення буде точним більшу частину часу, що недостатньо добре. Є деякі рішення цієї , як num.toPrecision, BigDecimal.js і accounting.js . Але я вважаю, що просто розбір рядка буде найпростішим і завжди точним.

На основі оновлення на добре написаному регулярному виразі з прийнятої відповіді @Gumbo, ця нова функція toFixed завжди працюватиме, як очікувалося.


Стара відповідь, не завжди точна.

Розкажіть власну функцію FiFi:

function toFixed(num, fixed) {
    fixed = fixed || 0;
    fixed = Math.pow(10, fixed);
    return Math.floor(num * fixed) / fixed;
}

7
toFixed (4,56, 2) = 4,55
крис

2
Так багато з цих відповідей мають множення всередині функції Math.floor (). У деяких випадках це не вдасться! Арифметика з плаваючою комою не є точною, і вам потрібно використовувати різні методи.
Ніко Вестердейл

1
функція toFixedCustom (число, фіксовано) {var re = new RegExp ('^ -? \\ d + (?: \. \\ d {0,' + (фіксований || -1) + '})?'); if (num.toString (). match (re)) {return num.toString (). match (re) [0]; }}
Райан Августин

1
Оновлена ​​відповідь не буде достатньою для великої чи малої кількості, яку би представляв javascript у науковій нотації. toFixed(0.0000000052, 2)врожайність '5,2'. Це можна виправити, скориставшись return num.toFixed(fixed+1).match(re)[0];повідомленням, що я використовую toFixed з одним десятковим місцем над ціллю, щоб уникнути округлення, а потім запустити ваш
регекс-

34

Я вирішив написати це замість того, щоб вручну видалити залишки з рядками, тому мені не доведеться мати справу з математичними проблемами, які поставляються з цифрами:

num = num.toString(); //If it's not already a String
num = num.slice(0, (num.indexOf("."))+3); //With 3 exposing the hundredths place
Number(num); //If you need it back as a Number

Це дасть вам "15,77" з числом = 15,7784514;


5
Якщо ви не примушуєте десятковий знак, ви можете додати умовний випадок, якщо ви зустрінете цілі числа. Ось так: num = num.toString (); if (num.indexOf (".")> 0) {num = num.slice (0, (num.indexOf (".")) + 3)}; Число (число);
ベ ン ノ ス ケ

1
приємно, якщо у нього є десяткові знаки, але якщо це ціле число, це не вдасться
Руслан Лопес

Якщо число 0,00000052, то буде неправильно отримувати 5,2е
Васант

1
@Vasanth Якщо число 0,00000052, воно повертає "0,00". Можливо, відповідь відредаговано з
Дреная

Так, це не в
кращих

18

Жовтень 2017 року

Загальне рішення для обрізання (без округлення) числа до п’ятої десяткової цифри та перетворення його в рядок із точно n n десятковими цифрами для будь-якого n≥0.

function toFixedTrunc(x, n) {
  const v = (typeof x === 'string' ? x : x.toString()).split('.');
  if (n <= 0) return v[0];
  let f = v[1] || '';
  if (f.length > n) return `${v[0]}.${f.substr(0,n)}`;
  while (f.length < n) f += '0';
  return `${v[0]}.${f}`
}

де x може бути числом (яке перетворюється на рядок) або рядком.

Ось кілька тестів на n = 2 (включаючи те, що вимагає ОП):

0           => 0.00
0.01        => 0.01
0.5839      => 0.58
0.999       => 0.99
1.01        => 1.01
2           => 2.00
2.551       => 2.55
2.99999     => 2.99
4.27        => 4.27
15.7784514  => 15.77
123.5999    => 123.59
0.000000199 => 1.99 *

* Як зазначалося в примітці, це пов’язано з неявним перетворенням JavaScript в експоненційне значення для "1,99е-7" та для деяких інших значень n:

15.001097   => 15.0010 (n=4)
0.000003298 => 0.0000032 (n=7)
0.000003298257899 => 0.000003298257 (n=12)

2
toFixedTrunc(0.000000199, 2) // 1.99
Maharramoff

1
@ShamkhalMaharramov: якщо відкрити консоль розробки та ввести 0,000000199, що ти отримуєш? Ви отримуєте 1,99е-7. Крім того, якщо ви введете 0,000000199.toString (), що ви отримуєте? Ви отримуєте "1.99e-7" Отже, коли ви переходите до 0,000000199 до функції, вона закінчує роботу над "1.99e-7" не "0,000000199" і "правильно" повертає "1,99". Дивіться ecma-international.org/ecma-262/6.0/…
SC1000

13

parseInt швидше, ніж Math.floor

function floorFigure(figure, decimals){
    if (!decimals) decimals = 2;
    var d = Math.pow(10,decimals);
    return (parseInt(figure*d)/d).toFixed(decimals);
};

floorFigure(123.5999)    =>   "123.59"
floorFigure(123.5999, 3) =>   "123.599"

2
це не вдається з 1234567.89
Руслан Лопес

Не могли б ви розробити Лопеса?
zardilior

3
полФигура (4,56, 2) = 4,55
крис

7
num = 19.66752
f = num.toFixed(3).slice(0,-1)
alert(f)

Це повернеться 19,66


5
(4.9999) .toFixed (3) .slice (0, -1) повертає 5.00, очікуваний результат - 4,99.
Бруно Лемос

1
Я рекомендую замість цього використовувати щось на зразок .toFixed (6) .slice (0, -4).
Бруно Лемос

це ідеально, в моєму випадку це буває нормально. наприклад, якщо я хочу мати лише одне десяткове число, використовуйте num.toFixed (2) .slice (0, -1) (якщо число має 1,2356, воно повернеться 1,2)
Esteban Perez


5

Ці рішення діють, але мені здаються непотрібними. Мені особисто подобається використовувати оператор модуля для отримання залишку операції поділу та видалити його. Припустимо, що число = 15,7784514:

num-=num%.01;

Це еквівалентно вимові num = num - (num% .01).


Це цікаво Nijkokun, дякую, що вказав на це. Я ніколи не стикався з проблемами використання цієї методики, але, очевидно, я повинен більш детально розглянути такі випадки. В якості альтернативи ви можете використовувати ((num * = 100) - (num% 1)) / 100, що вирішує цю проблему. У моєму випадку пріоритетним є швидкість виконання через обсяг розрахунків, до яких я застосовую це, і це найшвидший спосіб досягти цього, що я знайшов.
jtrick

1
Сенс полягав у тому, щоб уникнути пошуку об’єктів та функцій та перетворень, що вимагаються в інших пропонованих рішеннях. Дякуємо за відгук!
jtrick

1
також не вдається з негативом, як -5
Руслан Лопес

Мене також цікавить швидке округлення, як би ви зробили цей код робити 1 десяткове?
thednp

5

Відповіді тут не допомогли мені, воно продовжувало округлювати чи давати мені неправильну десяткову.

моє рішення перетворює вашу десяткову в рядок, витягує символи, а потім повертає всю справу як число.

function Dec2(num) {
  num = String(num);
  if(num.indexOf('.') !== -1) {
    var numarr = num.split(".");
    if (numarr.length == 1) {
      return Number(num);
    }
    else {
      return Number(numarr[0]+"."+numarr[1].charAt(0)+numarr[1].charAt(1));
    }
  }
  else {
    return Number(num);
  }  
}

Dec2(99); // 99
Dec2(99.9999999); // 99.99
Dec2(99.35154); // 99.35
Dec2(99.8); // 99.8
Dec2(10265.985475); // 10265.98

Dec2 (99) повинен повернутися 99.00
VPaul

5

Моя версія для позитивних цифр:

function toFixed_norounding(n,p)
{
    var result = n.toFixed(p);
    return result <= n ? result: (result - Math.pow(0.1,p)).toFixed(p);
}

Швидкий, гарний, очевидний. (версія для додатних цифр)


потрібно було не округлення для плаваючих значень (наприклад, грошей), лише 1 десяткове. Вищенаведена функція повинна бути «відповіддю» цієї теми, вона відмінна, працює як шарм. привіт автору & спасибі :)))
Адріан Танас

Не вдалося отримати негативне значення. -0.7752. Перевірте це toFixed_norounding(-0.7752,2)повертається -0.78замість-0.77
Лінг Лоенг

4

Наступний код працює для мене дуже добре:

num.toString().match(/.\*\\..{0,2}|.\*/)[0];

Я додам необов’язковий знак мінус, щоб зробити його ідеальним -?;)
Руслан Лопес

3

Я виправив, використовуючи наступний простий спосіб -

var num = 15.7784514;
Math.floor(num*100)/100;

Результати будуть 15,77


Вона не працює з негативними значеннями: -15.7784514повертається-15.78
Климент Baconnier

3

Просто обріжте цифри:

function truncDigits(inputNumber, digits) {
  const fact = 10 ** digits;
  return Math.floor(inputNumber * fact) / fact;
}

3

Ще одне лінійне рішення:

number = Math.trunc(number*100)/100

Я використовував 100, тому що ви хочете усікати до другої цифри, але більш гнучким рішенням буде:

number = Math.trunc(number*Math.pow(10, digits))/Math.pow(10, digits)

де цифри - кількість десяткових цифр, яку потрібно зберегти.

Детальні відомості та сумісність веб-переглядачів див. У специфікаціях Math.trunc .


1
Це найкраща відповідь, якщо вам не потрібно підтримувати IE11.
TJ.

2

Ось ви. Відповідь, яка показує ще один спосіб вирішення проблеми:

// For the sake of simplicity, here is a complete function:
function truncate(numToBeTruncated, numOfDecimals) {
    var theNumber = numToBeTruncated.toString();
    var pointIndex = theNumber.indexOf('.');
    return +(theNumber.slice(0, pointIndex > -1 ? ++numOfDecimals + pointIndex : undefined));
}

Зверніть увагу на використання + перед кінцевим виразом. Тобто перетворити наш усічений, нарізаний рядок назад у тип номера.

Сподіваюся, це допомагає!


1
Мені подобається простота такого підходу, і я вважаю, що всі рішення, які уникають використання математики, є більш підходящими для вирішення цієї проблеми. Отже, використання slice () тощо - це правильний шлях вперед. Єдиною перевагою мого методу є те, що він обробляє числа, передані в них, - це рядки [оточені лапками [одиночний / подвійний]]. Чомусь вищевказана функція видала помилку у FF, коли я це робив: console.log ('усікати ("0.85156", 2)', усікати ("0.85156", 2));
Чарльз Робертсон

2

усікати без нулів

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

або

function toTrunc(value,n){
    x=(value.toString()+".0").split(".");
    return parseFloat(x[0]+"."+x[1].substr(0,n));
}

тест:

toTrunc(17.4532,2)  //17.45
toTrunc(177.4532,1) //177.4
toTrunc(1.4532,1)   //1.4
toTrunc(.4,2)       //0.4

обрізати нулями

function toTruncFixed(value,n){
    return toTrunc(value,n).toFixed(n);
}

тест:

toTrunc(17.4532,2)  //17.45
toTrunc(177.4532,1) //177.4
toTrunc(1.4532,1)   //1.4
toTrunc(.4,2)       //0.40

2

Це добре спрацювало для мене. Я сподіваюся, що це вирішить і ваші проблеми.

function toFixedNumber(number) {
    const spitedValues = String(number.toLocaleString()).split('.');
    let decimalValue = spitedValues.length > 1 ? spitedValues[1] : '';
    decimalValue = decimalValue.concat('00').substr(0,2);

    return '$'+spitedValues[0] + '.' + decimalValue;
}

// 5.56789      ---->  $5.56
// 0.342        ---->  $0.34
// -10.3484534  ---->  $-10.34 
// 600          ---->  $600.00

function convertNumber(){
  var result = toFixedNumber(document.getElementById("valueText").value);
  document.getElementById("resultText").value = result;
}


function toFixedNumber(number) {
        const spitedValues = String(number.toLocaleString()).split('.');
        let decimalValue = spitedValues.length > 1 ? spitedValues[1] : '';
        decimalValue = decimalValue.concat('00').substr(0,2);

        return '$'+spitedValues[0] + '.' + decimalValue;
}
<div>
  <input type="text" id="valueText" placeholder="Input value here..">
  <br>
  <button onclick="convertNumber()" >Convert</button>
  <br><hr>
  <input type="text" id="resultText" placeholder="result" readonly="true">
</div>


2

Простий спосіб зробити це наступним, але необхідно забезпечити, щоб параметр суми був заданий у вигляді рядка.

function truncate(amountAsString, decimals = 2){
  var dotIndex = amountAsString.indexOf('.');
  var toTruncate = dotIndex !== -1  && ( amountAsString.length > dotIndex + decimals + 1);
  var approach = Math.pow(10, decimals);
  var amountToTruncate = toTruncate ? amountAsString.slice(0, dotIndex + decimals +1) : amountAsString;  
  return toTruncate
    ?  Math.floor(parseFloat(amountToTruncate) * approach ) / approach
    :  parseFloat(amountAsString);

}

console.log(truncate("7.99999")); //OUTPUT ==> 7.99
console.log(truncate("7.99999", 3)); //OUTPUT ==> 7.999
console.log(truncate("12.799999999999999")); //OUTPUT ==> 7.99

2

function formatLimitDecimals(value, decimals) {
  value = value.toString().split('.')

  if (value.length === 2) {
    return Number([value[0], value[1].slice(0, decimals)].join('.'))
  } else {
    return Number(value[0]);
  }
}

console.log(formatLimitDecimals(4.156, 2)); // 4.15
console.log(formatLimitDecimals(4.156, 8)); // 4.156
console.log(formatLimitDecimals(4.156, 0)); // 4


1

Раніше я (num-0.05).toFixed(1)отримував другий десятковий шар.


1

Моє рішення в машинописі (легко переноситься на JS):

/**
 * Returns the price with correct precision as a string
 *
 * @param   price The price in decimal to be formatted.
 * @param   decimalPlaces The number of decimal places to use
 * @return  string The price in Decimal formatting.
 */
type toDecimal = (price: number, decimalPlaces?: number) => string;
const toDecimalOdds: toDecimal = (
  price: number,
  decimalPlaces: number = 2,
): string => {
  const priceString: string = price.toString();
  const pointIndex: number = priceString.indexOf('.');

  // Return the integer part if decimalPlaces is 0
  if (decimalPlaces === 0) {
    return priceString.substr(0, pointIndex);
  }

  // Return value with 0s appended after decimal if the price is an integer
  if (pointIndex === -1) {
    const padZeroString: string = '0'.repeat(decimalPlaces);

    return `${priceString}.${padZeroString}`;
  }

  // If numbers after decimal are less than decimalPlaces, append with 0s
  const padZeroLen: number = priceString.length - pointIndex - 1;
  if (padZeroLen > 0 && padZeroLen < decimalPlaces) {
    const padZeroString: string = '0'.repeat(padZeroLen);

    return `${priceString}${padZeroString}`;
  }

  return priceString.substr(0, pointIndex + decimalPlaces + 1);
};

Тестові приклади:

  expect(filters.toDecimalOdds(3.14159)).toBe('3.14');
  expect(filters.toDecimalOdds(3.14159, 2)).toBe('3.14');
  expect(filters.toDecimalOdds(3.14159, 0)).toBe('3');
  expect(filters.toDecimalOdds(3.14159, 10)).toBe('3.1415900000');
  expect(filters.toDecimalOdds(8.2)).toBe('8.20');

Будь-які поліпшення?


0

Розкажіть власну toFixedфункцію: для позитивних значень Math.floorпрацює чудово.

function toFixed(num, fixed) {
    fixed = fixed || 0;
    fixed = Math.pow(10, fixed);
    return Math.floor(num * fixed) / fixed;
}

Для від'ємних значень Math.floor- це кругла величина. Таким чином, ви можете використовувати Math.ceilзамість цього.

Приклад,

Math.ceil(-15.778665 * 10000) / 10000 = -15.7786
Math.floor(-15.778665 * 10000) / 10000 = -15.7787 // wrong.

5
Так багато з цих відповідей мають множення всередині функції Math.floor (). У деяких випадках це не вдасться! Арифметика з плаваючою комою не є точною, і вам потрібно використовувати різні методи.
Ніко Вестердейл

0

Друге рішення Gumbo, з регулярним виразом, працює, але повільне через регулярне вираження. Перше рішення Gumbo провалюється в певних ситуаціях через неточність у числах з плаваючими точками. Дивіться JSFiddle для демонстрації та еталону. Друге рішення займає близько 1636 наносекунд на дзвінок у моїй теперішній системі, процесорі Intel Core i5-2500 на частоті 3,30 ГГц.

Написане нами рішення передбачає додавання невеликої компенсації, щоб подбати про неточність плаваючої точки. Це в основному миттєво, тобто в порядку наносекунд. Я набрав 2 наносекунди на дзвінок, але таймери JavaScript не дуже точні або чіткі. Ось JS Fiddle та код.

function toFixedWithoutRounding (value, precision)
{
    var factorError = Math.pow(10, 14);
    var factorTruncate = Math.pow(10, 14 - precision);
    var factorDecimal = Math.pow(10, precision);
    return Math.floor(Math.floor(value * factorError + 1) / factorTruncate) / factorDecimal;
}

var values = [1.1299999999, 1.13, 1.139999999, 1.14, 1.14000000001, 1.13 * 100];

for (var i = 0; i < values.length; i++)
{
    var value = values[i];
    console.log(value + " --> " + toFixedWithoutRounding(value, 2));
}

for (var i = 0; i < values.length; i++)
{
    var value = values[i];
    console.log(value + " --> " + toFixedWithoutRounding(value, 4));
}

console.log("type of result is " + typeof toFixedWithoutRounding(1.13 * 100 / 100, 2));

// Benchmark
var value = 1.13 * 100;
var startTime = new Date();
var numRun = 1000000;
var nanosecondsPerMilliseconds = 1000000;

for (var run = 0; run < numRun; run++)
    toFixedWithoutRounding(value, 2);

var endTime = new Date();
var timeDiffNs = nanosecondsPerMilliseconds * (endTime - startTime);
var timePerCallNs = timeDiffNs / numRun;
console.log("Time per call (nanoseconds): " + timePerCallNs);

0

Спираючись на відповідь Девіда Д :

function NumberFormat(num,n) {
  var num = (arguments[0] != null) ? arguments[0] : 0;
  var n = (arguments[1] != null) ? arguments[1] : 2;
  if(num > 0){
    num = String(num);
    if(num.indexOf('.') !== -1) {
      var numarr = num.split(".");
      if (numarr.length > 1) {
        if(n > 0){
          var temp = numarr[0] + ".";
          for(var i = 0; i < n; i++){
            if(i < numarr[1].length){
              temp += numarr[1].charAt(i);
            }
          }
          num = Number(temp);
        }
      }
    }
  }
  return Number(num);
}

console.log('NumberFormat(123.85,2)',NumberFormat(123.85,2));
console.log('NumberFormat(123.851,2)',NumberFormat(123.851,2));
console.log('NumberFormat(0.85,2)',NumberFormat(0.85,2));
console.log('NumberFormat(0.851,2)',NumberFormat(0.851,2));
console.log('NumberFormat(0.85156,2)',NumberFormat(0.85156,2));
console.log('NumberFormat(0.85156,4)',NumberFormat(0.85156,4));
console.log('NumberFormat(0.85156,8)',NumberFormat(0.85156,8));
console.log('NumberFormat(".85156",2)',NumberFormat(".85156",2));
console.log('NumberFormat("0.85156",2)',NumberFormat("0.85156",2));
console.log('NumberFormat("1005.85156",2)',NumberFormat("1005.85156",2));
console.log('NumberFormat("0",2)',NumberFormat("0",2));
console.log('NumberFormat("",2)',NumberFormat("",2));
console.log('NumberFormat(85156,8)',NumberFormat(85156,8));
console.log('NumberFormat("85156",2)',NumberFormat("85156",2));
console.log('NumberFormat("85156.",2)',NumberFormat("85156.",2));

// NumberFormat(123.85,2) 123.85
// NumberFormat(123.851,2) 123.85
// NumberFormat(0.85,2) 0.85
// NumberFormat(0.851,2) 0.85
// NumberFormat(0.85156,2) 0.85
// NumberFormat(0.85156,4) 0.8515
// NumberFormat(0.85156,8) 0.85156
// NumberFormat(".85156",2) 0.85
// NumberFormat("0.85156",2) 0.85
// NumberFormat("1005.85156",2) 1005.85
// NumberFormat("0",2) 0
// NumberFormat("",2) 0
// NumberFormat(85156,8) 85156
// NumberFormat("85156",2) 85156
// NumberFormat("85156.",2) 85156


0

Вже є відповідна відповідь з регулярним виразом і арифметичним обчисленням, ви також можете спробувати це

function myFunction() {
    var str = 12.234556; 
    str = str.toString().split('.');
    var res = str[1].slice(0, 2);
    document.getElementById("demo").innerHTML = str[0]+'.'+res;
}

// output: 12.23

0

Ось що це робиться за допомогою рядка

export function withoutRange(number) {
  const str = String(number);
  const dotPosition = str.indexOf('.');
  if (dotPosition > 0) {
    const length = str.substring().length;
    const end = length > 3 ? 3 : length;
    return str.substring(0, dotPosition + end);
  }
  return str;
}

0

Всі ці відповіді здаються трохи складними. Я б просто відняв 0,5 від вашого числа і використав toFixed ().


Ви мали на увазі 0,005?
Луан Нгуен

0

Найефективнішим рішенням (для 2-х розрядних цифр) є віднімання 0,005 перед викликом toFixed()

function toFixed2( num ) { return (num-0.005).toFixed(2) }

Негативні цифри теж будуть округлені вниз (далеко від нуля). ОП нічого не сказали про негативні цифри.


0

Я знаю, що вже є мало робочих прикладів, але я думаю, що варто запропонувати мій еквівалент String.toFixed, деякі можуть вважати це корисним.

Це моя альтернатива toFixed, яка не округляє числа, просто скорочує їх або додає нулі відповідно до заданої точності. Для надто довгого числа використовується вбудоване округлення JS, коли точність дорівнює. Функція працює на все проблемне число, яке я знайшов у стеці.

function toFixedFixed(value, precision = 0) {
    let stringValue = isNaN(+value) ? '0' : String(+value);

    if (stringValue.indexOf('e') > -1 || stringValue === 'Infinity' || stringValue === '-Infinity') {
        throw new Error('To large number to be processed');
    }

    let [ beforePoint, afterPoint ] = stringValue.indexOf('.') > -1 ? stringValue.split('.') : [ stringValue, ''];

    // Force automatic rounding for some long real numbers that ends with 99X, by converting it to string, cutting off last digit, then adding extra nines and casting it on number again
    // e.g. 2.0199999999999996: +('2.019999999999999' + '9999') will give 2.02
    if (stringValue.length >= 17 && afterPoint.length > 2 && +afterPoint.substr(afterPoint.length - 3) > 995) {
        stringValue = String(+(stringValue.substr(0, afterPoint.length - 1) + '9'.repeat(stringValue.split('.').shift().length + 4)));
        [ beforePoint, afterPoint ] = String(stringValue).indexOf('.') > -1 ? stringValue.split('.') : [ stringValue, ''];
    }

    if (precision === 0) {
        return beforePoint;
    } else if (afterPoint.length > precision) {
        return `${beforePoint}.${afterPoint.substr(0, precision)}`;
    } else {
        return `${beforePoint}.${afterPoint}${'0'.repeat(precision - afterPoint.length)}`;
    }
}

Майте на увазі, що точність може не оброблятися належним чином для чисел довжиною 18 і більше, наприклад, 64-бітний Chrome обведе її або додасть "e +" / "e-", щоб зберегти довжину номера в 18.

Якщо ви хочете виконувати операції з реальними числами, то безпечніше помножити їх Math.sqrt(10, precision)спочатку, зробіть обчислення, а потім зануріть результат на значення множника.

Приклад:

0.06 + 0.01є 0.06999999999999999, і кожна функція форматування, яка не є округленням, обріже її 0.06для точності2 .

Але якщо ви виконаєте таку ж операцію з множником і дільником:, (0.06 * 100 + 0.01 * 100) / 100ви отримаєте 0.07.

Ось чому так важливо використовувати такий множник / дільник при роботі з реальними числами в JavaScript, особливо коли ви підраховуєте гроші ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.