Skróć liczbę do dwóch miejsc po przecinku bez zaokrąglania

195

Załóżmy, że mam wartość 15.7784514, chcę wyświetlić ją 15,77 bez zaokrąglania.

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));

Prowadzi do -

15.8
15.78
15.778
15.7784514000 

Jak wyświetlić 15,77?

tempid
źródło
3
Kusi mnie pytanie, dlaczego nie chcesz zaokrąglać? Wydaje się niepoprawny, bez względu na to, gdzie ...
Camilo Martin
38
Jest to przydatne podczas wyświetlania waluty.
Richard Ye,
@ mik01aj - Podczas wyświetlania waluty bardziej powszechne jest obcinanie obliczonych wartości niż ich zaokrąglanie. Na przykład większość formularzy podatkowych w USA obcina zamiast okrągłych obliczonych centów ułamkowych. W takim przypadku obcięta wartość jest poprawną wartością.
Steven Byks,
4
@CamiloMartin istnieje ogromna różnica między długiem w wysokości 1,49 miliarda dolarów a 1,0 miliarda dolarów.
Broda Noel
3
Istnieje również ogromna różnica między 1,49 miliarda a 1,50 miliarda dolarów. To 100 milionów dolarów.
Liga

Odpowiedzi:

227

Konwertuj liczbę na ciąg znaków, dopasuj liczbę do drugiego miejsca po przecinku:

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>

W toFixedniektórych przypadkach metoda ta zawiedzie toString, więc bądź bardzo ostrożny.

Gumbo
źródło
22
+1 To powinno rozwiązać problem zaokrąglania. Ja bym jeszcze wyjścia, wynik powyżej użyciu toFixed, choć tak: (Math.floor(value * 100) / 100).toFixed(2). Jak zapewne wiesz, dziwne precyzyjne rzeczy mogą się zdarzyć z wartościami zmiennoprzecinkowymi (a po drugiej stronie spektrum, jeśli liczba się zdarzy 15, brzmi tak, jak chce OP 15.00).
TJ Crowder
1
hehe, lub jeśli połączysz oba:Number((15.7784514000*100).toString().match(/^\d+/)/100);
skobaljic
27
Math.floor (wartość * 100) / 100 nie będzie działać, jeśli wartość = 4,27 poważnie, spróbuj.
Dark Hippo
3
@DarkHippo To jest, ponieważ 4.27 to w rzeczywistości 4.26999999999, Math.round jest ogólnie lepszym rozwiązaniem, choć nie jest odpowiedzią na pierwotne pytanie. Realistycznie biorąc pod uwagę, że wyjście jest łańcuchem, należy to zrobić za pomocą manipulacji łańcuchem zamiast rozwiązania numerycznego ze wszystkimi zmiennoprzecinkowymi zmiennymi.
BJury,
3
... to nie brzmi dobrze. Konwersja między typami w każdych okolicznościach wydaje się ronda i jest niebezpieczna. Chyba że naprawdę zaawansowany programista twierdziłby, że „wszystkie typy są tylko strumieniami” czy coś w tym rodzaju.
JackHasaKeyboard
66

Aktualizacja 5 listopada 2016 r

Nowa odpowiedź, zawsze dokładna

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

Ponieważ matematyka zmiennoprzecinkowa w javascript zawsze będzie miała przypadki krawędzi, poprzednie rozwiązanie będzie przez większość czasu dokładne, co nie jest wystarczająco dobre. Istnieje kilka rozwiązań tego typu num.toPrecision, takich jak BigDecimal.js i rachunkowości.js . Uważam jednak, że samo parsowanie łańcucha będzie najprostsze i zawsze dokładne.

Opierając aktualizację na dobrze napisanym wyrażeniu regularnym z zaakceptowanej odpowiedzi @Gumbo, ta nowa funkcja toFixed zawsze będzie działać zgodnie z oczekiwaniami.


Stara odpowiedź, nie zawsze dokładna.

Rzuć własną funkcję toFixed:

function toFixed(num, fixed) {
    fixed = fixed || 0;
    fixed = Math.pow(10, fixed);
    return Math.floor(num * fixed) / fixed;
}
guya
źródło
7
toFixed (4.56, 2) = 4.55
cryss 31.10.16
2
Tak wiele z tych odpowiedzi ma mnożenie w funkcji Math.floor (). To się nie powiedzie w przypadku niektórych liczb! Arytmetyka zmiennoprzecinkowa nie jest dokładna i musisz użyć różnych metod.
Nico Westerdale
1
function toFixedCustom (num, fixed) {var re = new RegExp ('^ -? \\ d + (?: \. \\ d {0,' + (fixed || -1) + '})?'); if (num.toString (). match (re)) {return num.toString (). match (re) [0]; }}
Ryan Augustine
1
Zaktualizowana odpowiedź nie powiedzie się w przypadku liczby wystarczająco dużej lub małej, którą javascript reprezentowałby w notacji naukowej. toFixed(0.0000000052, 2)daje „5,2”. Można to naprawić za pomocą return num.toFixed(fixed+1).match(re)[0];Zawiadomienia Używam toFixed z jednym miejscem dziesiętnym nad celem, aby uniknąć zaokrąglania, a następnie uruchamiając dopasowanie wyrażenia regularnego
Netherdan
33

Zdecydowałem się napisać to zamiast tego, aby ręcznie usunąć resztę za pomocą ciągów, aby nie musieć zajmować się matematyką związaną z liczbami:

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

To da ci „15,77” z num = 15,7784514;

ベ ン ノ ス ケ
źródło
5
Jeśli nie wymuszasz ułamka dziesiętnego, możesz chcieć dodać warunek w przypadku napotkania liczb całkowitych. W ten sposób: num = num.toString (); if (num.indexOf (".")> 0) {num = num.slice (0, (num.indexOf (".")) + 3)}; Liczba (liczba);
ベ ン ノ ス ケ
1
fajnie, jeśli ma miejsca po przecinku, ale jeśli jest liczbą całkowitą, zawiedzie
Ruslan López
Jeżeli num jest 0.00000052, to będzie źle się 5.2e
Vasanth
1
@Vasanth Jeśli liczba wynosi 0,00000052, zwraca „0,00”. Może odpowiedź została zredagowana od tego czasu
Drenai,
Tak, nie udaje się to w
skrajnych
18

Październik 2017 r

Ogólne rozwiązanie w celu obcięcia (bez zaokrąglania) liczby do n-tej cyfry dziesiętnej i przekształcenia jej w ciąg o dokładnie n cyfr dziesiętnych dla dowolnego 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}`
}

gdzie x może być liczbą (która jest konwertowana na ciąg) lub ciągiem.

Oto kilka testów dla n = 2 (włączając ten wymagany przez OP):

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 *

* Jak wspomniano w notatce, wynika to z domyślnej konwersji javascript na wykładniczą dla „1.99e-7” i dla niektórych innych wartości n:

15.001097   => 15.0010 (n=4)
0.000003298 => 0.0000032 (n=7)
0.000003298257899 => 0.000003298257 (n=12)
SC1000
źródło
2
toFixedTrunc(0.000000199, 2) // 1.99
Maharramoff,
1
@ShamkhalMaharramov: jeśli otworzysz konsolę programistyczną i wprowadzisz 0,000000199, co otrzymasz? Dostajesz 1,99e-7. Ponadto, jeśli wpiszesz 0.000000199.toString (), co otrzymasz? Otrzymujesz „1,99e-7”. Zatem po przekazaniu do funkcji 0,000000199 kończy się to działaniem na „1.99e-7”, a nie „0,000000199”, a „poprawnie” zwraca „1,99”. Zobacz ecma-international.org/ecma-262/6.0/…
SC1000,
13

parseInt jest szybszy niż 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"
Martin Varmus
źródło
2
kończy się niepowodzeniem z 1234567.89
Ruslan López
Czy mógłbyś opracować Lopeza?
zardilior
3
floorFigure (4.56, 2) = 4.55
cryss 31.10.16
7
num = 19.66752
f = num.toFixed(3).slice(0,-1)
alert(f)

Zwróci 19,66

Alex Peng
źródło
5
(4.9999) .toFixed (3) .slice (0, -1) zwraca 5,00, oczekiwany wynik to 4,99.
Bruno Lemos,
1
Zalecam użycie czegoś takiego jak .toFixed (6) .slice (0, -4).
Bruno Lemos,
to jest idealne, w moim przypadku jest w porządku. na przykład, jeśli chcę mieć tylko jedną liczbę dziesiętną, użyj num. do Fixed (2). slice (0, -1) (jeśli num ma 1.2356, zwróci 1,2)
Esteban Perez
7

Po prostu zrób to

number = parseInt(number * 100)/100;
Imran Pollob
źródło
4
parseInt (8,2 * 100) = 819
VPaul
5

Te rozwiązania działają, ale dla mnie wydają się niepotrzebnie skomplikowane. Osobiście lubię używać operatora modułu, aby uzyskać pozostałą część operacji dzielenia, i usunąć ją. Zakładając, że num = 15,7784514:

num-=num%.01;

Jest to równoważne z wypowiedzeniem num = num - (num% .01).

jtrick
źródło
To ciekawe, Nijkokun, dziękuję za zwrócenie na to uwagi. Nigdy nie miałem problemów z użyciem tej techniki, ale oczywiście powinienem przyjrzeć się bliżej takim przypadkom. Alternatywnie możesz użyć ((num * = 100) - (num% 1)) / 100, który rozwiązuje ten problem. W moim przypadku priorytetem jest szybkość wykonywania ze względu na liczbę obliczeń, do których się to stosuje, i jest to najszybszy sposób na osiągnięcie tego, co znalazłem.
jtrick
1
Chodziło o to, aby uniknąć wyszukiwania obiektów i funkcji oraz konwersji wymaganych w innych oferowanych rozwiązaniach. Dziękujemy za opinię!
jtrick
1
również zawodzi z negatywnymi jak -5
Ruslan López
Interesuje mnie również szybkie zaokrąglanie, w jaki sposób zrobiłbyś ten kod z dokładnością do 1 miejsca po przecinku?
thednp
5

Odpowiedzi tutaj nie pomogły mi, zaokrąglały się w górę lub podawały niewłaściwy ułamek dziesiętny.

moje rozwiązanie konwertuje liczbę dziesiętną na ciąg, wyodrębnia znaki, a następnie zwraca całość jako liczbę.

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
David D.
źródło
Dec2 (99) powinien zwrócić 99,00
VPaul
5

Moja wersja na liczby dodatnie:

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

Szybki, ładny, oczywisty. (wersja na liczby dodatnie)

Alfa i Omega
źródło
potrzebował nie zaokrąglania wartości zmiennoprzecinkowych (np. pieniędzy), z tylko 1 miejscem po przecinku. Powyższa funkcja powinna być „odpowiedzią” tego tematu, jest doskonała, działa jak urok. pozdrawiam autora i dziękuję. :)))
Adrian Tanase
Niepowodzenie dla wartości ujemnej. -0.7752. Sprawdź, czy toFixed_norounding(-0.7752,2)powraca -0.78zamiast-0.77
Ling Loeng
4

Poniższy kod działa dla mnie bardzo dobrze:

num.toString().match(/.\*\\..{0,2}|.\*/)[0];
MISSIRIA
źródło
Dodam opcjonalny znak minus, aby był idealny -?;)
Ruslan López
3

Naprawiłem za pomocą następującego prostego sposobu-

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

Wyniki będą 15.77

oms
źródło
Nie działa z wartościami ujemnymi: -15.7784514zwraca-15.78
Clément Baconnier,
3

Po prostu skróć cyfry:

function truncDigits(inputNumber, digits) {
  const fact = 10 ** digits;
  return Math.floor(inputNumber * fact) / fact;
}
Aral Roca
źródło
3

Inne rozwiązanie jednowierszowe:

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

Użyłem 100, ponieważ chcesz skrócić do drugiej cyfry, ale bardziej elastycznym rozwiązaniem byłoby:

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

gdzie cyfry to liczba cyfr dziesiętnych do zachowania.

Zobacz specyfikacje Math.trunc, aby uzyskać szczegółowe informacje i zgodność przeglądarki.

remidej
źródło
1
To najlepsza odpowiedź, jeśli nie musisz obsługiwać IE11.
TJ.
2

Tu masz. Odpowiedź, która pokazuje jeszcze inny sposób rozwiązania problemu:

// 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));
}

Zwróć uwagę na użycie znaku + przed końcowym wyrażeniem. Oznacza to konwersję naszego obciętego, pokrojonego łańcucha z powrotem na typ liczbowy.

Mam nadzieję, że to pomoże!

Jakub Barczyk
źródło
1
Podoba mi się prostota tego podejścia i uważam, że wszystkie rozwiązania, które unikają używania matematyki, są bardziej odpowiednie do rozwiązania tego problemu. Tak więc użycie slice () itp. Jest właściwym rozwiązaniem. Jedyną zaletą mojej metody jest to, że będzie przetwarzać przekazywane liczby, które są ciągami znaków [otoczonymi znakami cudzysłowu [pojedynczy / podwójny]]. Z jakiegoś powodu powyższa funkcja zgłosiła błąd w FF, kiedy to zrobiłem: console.log („truncate („ 0.85156 ”, 2)”, truncate („0.85156”, 2));
Charles Robertson,
2

obcinaj bez zer

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

lub

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

test:

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

obciąć zerami

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

test:

toTrunc(17.4532,2)  //17.45
toTrunc(177.4532,1) //177.4
toTrunc(1.4532,1)   //1.4
toTrunc(.4,2)       //0.40
ShAkKiR
źródło
2

To działało dla mnie dobrze. Mam nadzieję, że rozwiąże to również twoje problemy.

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>

Sandaru
źródło
2

Łatwy sposób to zrobić, ale koniecznie upewnij się, że parametr kwota jest podany jako ciąg.

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
Felipe Santa
źródło
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

Ruben Morales Felix
źródło
1

Kiedyś (num-0.05).toFixed(1)dostawałem drugiego miejsca po przecinku.

王景飞
źródło
1

Moje rozwiązanie w maszynopisie (może być łatwo przeniesione do 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);
};

Przypadki testowe:

  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');

Jakieś ulepszenia?

VPaul
źródło
0

Rzuć własną toFixedfunkcję: dla wartości dodatnich Math.floordziała dobrze.

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

Dla wartości ujemnych Math.floorjest to runda wartości. Możesz więc użyć Math.ceilzamiast tego.

Przykład,

Math.ceil(-15.778665 * 10000) / 10000 = -15.7786
Math.floor(-15.778665 * 10000) / 10000 = -15.7787 // wrong.
Boopathi Sakthivel
źródło
5
Tak wiele z tych odpowiedzi ma mnożenie w funkcji Math.floor (). To się nie powiedzie w przypadku niektórych liczb! Arytmetyka zmiennoprzecinkowa nie jest dokładna i musisz użyć różnych metod.
Nico Westerdale,
0

Drugie rozwiązanie Gumbo, z wyrażeniem regularnym, działa, ale jest powolne z powodu wyrażenia regularnego. Pierwsze rozwiązanie Gumbo zawodzi w niektórych sytuacjach z powodu niedokładności liczb zmiennoprzecinkowych. Zobacz JSFiddle aby zobaczyć demonstrację i test porównawczy. Drugie rozwiązanie zajmuje około 1636 nanosekund na połączenie w moim obecnym systemie, procesor Intel Core i5-2500 przy 3,30 GHz.

Rozwiązanie, które napisałem, polega na dodaniu niewielkiej kompensacji w celu wyeliminowania niedokładności zmiennoprzecinkowej. Jest to w zasadzie natychmiastowe, tj. Rzędu nanosekund. Taktowałem 2 nanosekundy na każde połączenie, ale liczniki JavaScript nie są bardzo precyzyjne ani szczegółowe. Oto skrzypce JS i kod.

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);
Daniel Barbalace
źródło
0

Opierając się na Davida D's odpowiedzi:

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
Charles Robertson
źródło
0

Bardziej niezawodne jest uzyskanie dwóch punktów zmiennoprzecinkowych bez zaokrąglania.

Referencyjna odpowiedź

var number = 10.5859;
var fixed2FloatPoints = parseInt(number * 100) / 100;
console.log(fixed2FloatPoints);

Dziękuję Ci !

Jaydeep Mor
źródło
0

Już istnieje odpowiednia odpowiedź z wyrażeniem regularnym i obliczeniami arytmetycznymi, możesz także spróbować tego

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
król neo
źródło
0

Oto, co zrobiono z łańcuchem

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;
}
Kishan Vaghela
źródło
0

Wszystkie te odpowiedzi wydają się nieco skomplikowane. Chciałbym odjąć 0,5 od twojego numeru i użyć toFixed ().

Sean Mayes
źródło
Miałeś na myśli 0,005?
Luan Nguyen
0

Najbardziej wydajnym rozwiązaniem (dla 2 cyfr ułamkowych) jest odjęcie 0,005 przed wywołaniem toFixed()

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

Liczby ujemne również zostaną zaokrąglone w dół (od zera). OP nie powiedział nic o liczbach ujemnych.

Wiimm
źródło
0

Wiem, że istnieje już kilka działających przykładów, ale myślę, że warto zaproponować mój odpowiednik String.toFixed, niektórzy mogą uznać to za pomocne.

To moja alternatywa dla toFixed, która nie zaokrągla liczb, po prostu ją obciąża lub dodaje zera zgodnie z podaną precyzją. W przypadku bardzo długiej liczby używa wbudowanego zaokrąglania JS, gdy precyzja jest za długa. Funkcja działa dla wszystkich problematycznych liczb, które znalazłem na stosie.

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)}`;
    }
}

Pamiętaj, że precyzja może nie być właściwie obsługiwana dla liczb o długości 18 i większej, np. 64-bitowy Chrome zaokrągli ją lub doda „e +” / „e-”, aby utrzymać liczbę na 18.

Jeśli chcesz wykonywać operacje na liczbach rzeczywistych, bezpieczniej jest pomnożyć go przez Math.sqrt(10, precision)pierwsze, wykonać obliczenia, a następnie zanotować wynik według wartości mnożnika.

Przykład:

0.06 + 0.01jest 0.06999999999999999, a każda funkcja formatowania, która nie jest zaokrąglana, obetnie ją 0.06dla precyzji 2.

Ale jeśli wykonasz tę samą operację za pomocą mnożnika i dzielnika: (0.06 * 100 + 0.01 * 100) / 100otrzymasz 0.07.

Dlatego tak ważne jest, aby używać takiego mnożnika / dzielnika, gdy mamy do czynienia z liczbami rzeczywistymi w javascript, szczególnie przy obliczaniu pieniędzy ...

MagyaDEV
źródło