Formatowanie liczby z dokładnością do dwóch miejsc po przecinku w JavaScript

571

Mam ten wiersz kodu, który zaokrągla moje liczby do dwóch miejsc po przecinku. Ale dostaję takie liczby: 10,8, 2,4 itd. To nie jest mój pomysł na dwa miejsca po przecinku, więc jak mogę poprawić następujące?

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

Chcę liczb takich jak 10.80, 2.40 itd. Korzystanie z jQuery jest dla mnie w porządku.

Abs
źródło
1
Twój kod jest dokładnie tym, czego szukałem (aby zmniejszyć precyzję liczby zmiennoprzecinkowej do 7 miejsc po przecinku dla mniejszego pliku JSON) Pomijanie Math.pow dla prędkości val = Math.round (val * 10000000) / 10000000);
Paweł
Ponieważ aktualnie akceptowanych odpowiedź daje niewątpliwie zły wynik dla szerokiego zakresu wartości Dzięki obciążających niedokładności wrodzoną w liczbach ( 0.565, 0.575, 1.005), mogę zasugerować patrząc znowu na tej odpowiedzi , która dostaje je poprawić?
TJ Crowder
Może chcesz dołączyć bibliotekę sprintf dla JavaScript stackoverflow.com/questions/610406/…
Thilo,
Po prawidłowym zaokrągleniu za pomocą metody przesunięcia i zaokrąglenia miejsca dziesiętnego można użyć tej number.toFixed(x)metody do przekonwertowania go na ciąg znaków z wymaganą liczbą zer. Np. Zaokrąglij 1.34do 1.3metody przeglądarką, a następnie dodaj 1 zero i przekonwertuj na ciąg za pomocą 1.3.toFixed(2)(aby uzyskać "1.30").
Edward,

Odpowiedzi:

999

Aby sformatować liczbę za pomocą notacji ze stałym punktem, możesz po prostu użyć metody toFixed :

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

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

Zauważ, że toFixed()zwraca ciąg.

WAŻNE : Należy pamiętać, że toFixed nie zaokrągla 90% czasu, zwraca zaokrągloną wartość, ale w wielu przypadkach nie działa.

Na przykład:

2.005.toFixed(2) === "2.00"

AKTUALIZACJA:

Obecnie możesz korzystać z Intl.NumberFormatkonstruktora. Jest to część specyfikacji interfejsu API internacjonalizacji ECMAScript (ECMA402). Ma całkiem dobre wsparcie przeglądarki , w tym nawet IE11 i jest w pełni obsługiwana w node.js .

const formatter = new Intl.NumberFormat('en-US', {
   minimumFractionDigits: 2,      
   maximumFractionDigits: 2,
});

console.log(formatter.format(2.005)); // "2.01"
console.log(formatter.format(1.345)); // "1.35"

Alternatywnie możesz użyć toLocaleStringmetody, która wewnętrznie będzie korzystać z Intlinterfejsu API:

const format = (num, decimals) => num.toLocaleString('en-US', {
   minimumFractionDigits: 2,      
   maximumFractionDigits: 2,
});


console.log(format(2.005)); // "2.01"
console.log(format(1.345)); // "1.35"

Ten interfejs API zapewnia także szeroki wybór opcji formatowania, takich jak tysiące separatorów, symbole walut itp.

CMS
źródło
17
Nie działa konsekwentnie we wszystkich przeglądarkach, tzn. (0.09).toFixed(1);Daje 0,0 w IE8
ajbeaven 10.1011
41
naprawiono nie zaokrągla, możesz to zrobić najpierw: (Math.round (0.09)). toFixed (1);
rekans
32
@rekans: To źle. Math.Round(0.09)wróci, 0więc to zawsze da 0.0...
Chris
28
Jest to zły pomysł w większości sytuacji, w niektórych przypadkach konwertuje liczbę na ciąg lub liczbę zmiennoprzecinkową.
Ash Blue
80
Muszę się zgodzić z @AshBlue tutaj ... jest to bezpieczne tylko w przypadku formatowania prezentacji wartości. Może złamać kod przy dalszych obliczeniach. W przeciwnym razie Math.round(value*100)/100działa lepiej dla 2DP.
UpTheCreek
98

Jest to stary temat, ale wciąż najwyższe pozycje w wynikach Google, a oferowane rozwiązania mają ten sam problem dziesiętnych liczb zmiennoprzecinkowych. Oto (bardzo ogólna) funkcja, której używam dzięki 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));
}

Jak widzimy, nie występują następujące problemy:

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

Ta generyczność zapewnia również kilka fajnych rzeczy:

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

Teraz, aby odpowiedzieć na pytanie PO, należy wpisać:

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

Lub, dla bardziej zwięzłej, mniej ogólnej funkcji:

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

Możesz to nazwać za pomocą:

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

Różne przykłady i testy (dzięki @ tj-crowder !):

astorije
źródło
1
Jak nie ma prostego sposobu na zrobienie tego? ES6 na ratunek?
zero_cool
Dziękujemy za opublikowanie wypełnienia MDN. Na połączonej stronie MDN nie ma już wypełnienia. Zastanawiam się, dlaczego został usunięty ...
Król Holly,
43

Zazwyczaj dodaję to do mojej osobistej biblioteki, a po kilku sugestiach i użyciu rozwiązania @TIMINeutron, a następnie dostosowaniu go do długości dziesiętnej, ta najlepiej pasuje:

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

będzie działać dla zgłoszonych wyjątków.

Miguel
źródło
2
precision_round (1.275,2) wynosi 1.27?
allenhwkim
2
@Imre Zmień wartość zwracaną na (Math.round (num * Math.pow (10, dziesiętne)) / Math.pow (10, dziesiętne)). ToFixed (2); i nie będziesz już mieć tego problemu.
dkroy
6
gdzie deklarujesz „znak” i „dec”, jeśli twoja druga funkcja jest wybrana, czy nie powinna mieć tak niezdefiniowanej?
Ady Ngom
2
Dodałem obejście dla metody znaku missign w IE: gist.github.com/ArminVieweg/28647e735aa6efaba401
Armin
1
@Armin Poprawka sprawia, że ​​działa ona również w przeglądarce Safari. Oryginalna funkcja nie działała w przeglądarce Safari.
Dave
19

Nie wiem, dlaczego nie mogę dodać komentarza do poprzedniej odpowiedzi (być może jestem beznadziejnie ślepy, nie wiem), ale wpadłem na rozwiązanie, używając odpowiedzi @ Miguela:

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

I jego dwa komentarze (z @bighostkim i @Imre):

  • Problem z precise_round(1.275,2)brakiem zwrotu 1.28
  • Problem z precise_round(6,2)nie zwracaniem 6.00 (tak jak chciał).

Moje ostateczne rozwiązanie jest następujące:

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

Jak widać musiałem dodać trochę „korekty” (to nie jest to, co to jest, ale ponieważ Math.round jest stratny - możesz to sprawdzić na jsfiddle.net - to jedyny sposób, w jaki wiedziałem, jak to naprawić " to). Dodaje 0,001 do już wypełnionej liczby, więc dodaje 1trzy 0s po prawej stronie wartości dziesiętnej. Dlatego powinien być bezpieczny w użyciu.

Następnie dodałem, .toFixed(decimal)aby zawsze wyświetlać liczbę we właściwym formacie (z odpowiednią liczbą miejsc po przecinku).

To tyle. Wykorzystaj to dobrze;)

EDYCJA: dodano funkcjonalność do „korekty” liczb ujemnych.

tfrascaroli
źródło
2
„Korekta” jest w większości bezpieczna, ale np. precise_round(1.27499,2)Teraz zwraca również 1,28 ... To nie Math.roundjest stratne; sposób, w jaki komputery wewnętrznie przechowują wartości zmiennoprzecinkowe, jest. Zasadniczo jesteś skazany na niepowodzenie z niektórymi wartościami, zanim dane dotrą nawet do Twojej funkcji :)
Imre
@Imre, masz absolutną rację. Dlatego wyjaśniam, co tam robi 0,001, na wypadek, gdyby ktoś chciał uczynić go „bardziej precyzyjnym ” lub nawet go usunąć (jeśli zdarzy ci się mieć super komputer z 2 MB na pływak, co, jak sądzę, nikt tutaj nie robi ;)
tfrascaroli
1
W rzeczywistości specyfikacja języka jest dość specyficzna w kwestii używania 64 bitów dla wartości liczbowych, więc posiadanie / używanie superkomputera niczego by nie zmieniło :)
Imre
dla 0,001 można zastąpić dodając wiele zer w zależności od długości miejsc po przecinku. więc ..
Miguel
15

Jednym ze sposobów na uzyskanie 100% pewności, że otrzymasz liczbę z 2 miejscami po przecinku:

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

Jeśli powoduje to błędy zaokrąglania, możesz użyć następujących elementów, jak wyjaśnił James w swoim komentarzu:

(Math.round((num * 1000)/10)/100).toFixed(2)
Gerard de Visser
źródło
6
To najlepszy, najprostszy sposób na zrobienie tego. Jednak z powodu matematyki zmiennoprzecinkowej 1,275 * 100 = 127,4999999999999999, co może powodować drobne błędy w zaokrąglaniu. Aby to naprawić, możemy pomnożyć przez 1000 i podzielić przez 10, ponieważ (1,275 * 1000) / 10 = 127,5. Jak następuje: var answer = (Math.round((num * 1000)/10)/100).toFixed(2);
James Gould,
(Math.round ((1.015 * 1000) / 10) / 100) .toFixed (2) nadal daje 1.01, czy nie powinno to być 1.02?
gaurav5430,
14

toFixed (n) zapewnia n długości po przecinku; toPrecision (x) zapewnia x całkowitą długość.

Użyj tej metody poniżej

// 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

A jeśli chcesz, aby numer był stały, użyj

result = num.toFixed(2);
Syed Umar Ahmed
źródło
nie działa dobrze ... dla numeru num = 50.2349 należy napisać do Precision (3), aby uzyskać 50.2
Piotr Czyż
to tylko przykład, możesz to zmienić według własnych potrzeb @ PiotrCzyż
Syed Umar Ahmed
5

Nie znalazłem dokładnego rozwiązania tego problemu, więc stworzyłem własne:

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

Przykłady:

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

Florian Ignaz Eßl
źródło
2
Dzięki. Oto coś do przetestowania: jsfiddle.net/lamarant/ySXuF . Stosuję toFixed () do wartości przed jej zwróceniem, która dołącza prawidłową liczbę zer na końcu zwracanej wartości.
lamarant
nie działa dla wartości = 0,004990845956707237 i inprecise_round (wartość, 8) zwraca 0,00499085, ale musi zwrócić 0,00499084
MERT DOĞAN
3

@heridev i ja stworzyliśmy małą funkcję w jQuery.

Możesz spróbować dalej:

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

DEMO ONLINE:

http://jsfiddle.net/c4Wqn/

wicemistrz
źródło
1
Mogę docenić wkład, choć myślę, że dodanie elementów DOM i jQuery do miksu wydaje się nie wchodzi w zakres pytania.
Chris May
Nie powinieneś słuchać zdarzenia keyup, ponieważ wygląda to bardzo źle i nie aktywuje się po dodaniu czegoś za pomocą skryptu. Wolę słuchać tego inputwydarzenia. Nie powoduje to efektu migotania, a także strzela, gdy wchodzisz na pole za pomocą JS
Le 'nton
3

Problem z wartościami zmiennoprzecinkowymi polega na tym, że próbują one reprezentować nieskończoną liczbę (ciągłych) wartości za pomocą stałej liczby bitów. Więc oczywiście musi być jakaś strata w grze, a ty ugryziesz się z pewnymi wartościami.

Gdy komputer przechowuje 1,275 jako wartość zmiennoprzecinkową, tak naprawdę nie będzie pamiętał, czy był to 1.275, czy 1.27499999999999993, czy nawet 1.27500000000000002. Wartości te powinny dawać różne wyniki po zaokrągleniu do dwóch miejsc po przecinku, ale nie będą, ponieważ dla komputera wyglądają dokładnie tak samo po zapisaniu jako wartości zmiennoprzecinkowe i nie ma możliwości przywrócenia utraconych danych. Wszelkie dalsze obliczenia będą tylko kumulować taką niedokładność.

Jeśli więc precyzja ma znaczenie, od samego początku należy unikać wartości zmiennoprzecinkowych. Najprostsze opcje to

  • użyj oddanej biblioteki
  • używaj ciągów do przechowywania i przekazywania wartości (w połączeniu z operacjami ciągów)
  • używaj liczb całkowitych (np. możesz podać około setnych swojej rzeczywistej wartości, np. kwota w centach zamiast kwoty w dolarach)

Na przykład, używając liczb całkowitych do przechowywania setnych, funkcja znajdowania rzeczywistej wartości jest dość prosta:

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

W przypadku ciągów trzeba zaokrąglać, ale nadal jest to możliwe:

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

Zauważ, że ta funkcja zaokrągla wartość do najbliższej, wiąże się od zera , podczas gdy IEEE 754 zaleca zaokrąglanie do najbliższej, wiąże nawet jako domyślne zachowanie dla operacji zmiennoprzecinkowych. Takie modyfikacje pozostawiają czytelnikowi ćwiczenie :)

Imre
źródło
3

Oto prosty

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

Użyj jak alert(roundFloat(1.79209243929,4));

Jsfiddle

ow3n
źródło
2

Zaokrąglij swoją wartość dziesiętną, a następnie użyj toFixed(x)dla oczekiwanych cyfr.

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

Połączenie

parseDecimalRoundAndFixed (10.800243929,4) => 10,80 parseDecimalRoundAndFixed (10.807243929,2) => 10,81

HATCHA
źródło
2

Zaokrąglić w dół

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

Podsumowanie

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

Runda najbliższa

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

Scalono https://stackoverflow.com/a/7641824/1889449 i https://www.kirupa.com/html5/rounding_numbers_in_javascript.htm Dzięki im.

MERT DOĞAN
źródło
2

/**
 * 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

Amr Ali
źródło
2

Oto moje 1-liniowe rozwiązanie: Number((yourNumericValueHere).toFixed(2));

Oto co się dzieje:

1) Najpierw aplikujesz .toFixed(2)na liczbę, którą chcesz zaokrąglić miejsca dziesiętne. Zauważ, że to przekształci wartość na ciąg z liczby. Więc jeśli używasz Typescript, wygeneruje następujący błąd:

„Ciąg„ Type ”nie może być przypisany do„ number ””

2) Aby odzyskać wartość liczbową lub przekonwertować ciąg na wartość liczbową, po prostu zastosuj Number()funkcję na tej tak zwanej wartości „ciąg”.

Aby uzyskać wyjaśnienie, spójrz na poniższy przykład:

PRZYKŁAD: Mam kwotę, która ma do 5 cyfr po przecinku i chciałbym ją skrócić do 2 miejsc po przecinku. Robię to tak:

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

Devner
źródło
1

Umieść następujące w pewnym globalnym zakresie:

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

a następnie spróbuj :

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

Aktualizacja

Zauważ, że toFixed()może działać tylko dla liczby miejsc po przecinku, 0-20tzn. a.getDecimals(25)Może generować błąd javascript, więc aby się dostosować, możesz dodać dodatkowe sprawdzenie, tj.

Number.prototype.getDecimals = function ( decDigCount ) {
   return ( decDigCount > 20 ) ? this : this.toFixed(decDigCount);
}
Kamran Ahmed
źródło
1
Number(((Math.random() * 100) + 1).toFixed(2))

spowoduje to zwrócenie losowej liczby od 1 do 100 w zaokrągleniu do 2 miejsc po przecinku.

Johnathan Ralls
źródło
1

Korzystanie z tej odpowiedzi przez odniesienie: https://stackoverflow.com/a/21029698/454827

Buduję funkcję, aby uzyskać dynamiczne liczby dziesiętne:

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

tutaj działa przykład: https://jsfiddle.net/wpxLduLc/

ZiTAL
źródło
1

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>

Vishnu T Asok
źródło
1

W tych przykładach nadal będzie występować błąd przy próbie zaokrąglenia liczby 1.005 rozwiązaniem jest albo użycie biblioteki takiej jak Math.js lub tej funkcji:

function round(value: number, decimals: number) {
    return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
}
David Webster
źródło
1

Kilka miesięcy temu otrzymałem kilka pomysłów z tego postu, ale żadna z odpowiedzi tutaj ani odpowiedzi z innych postów / blogów nie poradziłyby sobie ze wszystkimi scenariuszami (np. Liczby ujemne i niektóre „szczęśliwe liczby”, które nasz tester znalazł). W końcu nasz tester nie znalazł żadnego problemu z tą metodą poniżej. Wklejanie fragmentu mojego kodu:

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

Mam także komentarze do kodu (przepraszam, zapomniałem już o wszystkich szczegółach) ... Publikuję tutaj swoją odpowiedź w celu późniejszego wykorzystania:

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).
remondo
źródło
0

Naprawiam problem modyfikatora. Obsługuje tylko 2 miejsca dziesiętne.

$(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>

bamossza
źródło
0
(Math.round((10.2)*100)/100).toFixed(2)

To powinno dać: 10.20

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

To powinno dać: 0.05

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

To powinno dać: 4.04

itp.

Anthony Ruffino
źródło
0

/*Due to all told stuff. You may do 2 things for different purposes:
When showing/printing stuff use this in your alert/innerHtml= contents:
YourRebelNumber.toFixed(2)*/

var aNumber=9242.16;
var YourRebelNumber=aNumber-9000;
alert(YourRebelNumber);
alert(YourRebelNumber.toFixed(2));

/*and when comparing use:
Number(YourRebelNumber.toFixed(2))*/

if(YourRebelNumber==242.16)alert("Not Rounded");
if(Number(YourRebelNumber.toFixed(2))==242.16)alert("Rounded");

/*Number will behave as you want in that moment. After that, it'll return to its defiance.
*/

Christian Læirbag
źródło
0

Jest to bardzo proste i działa tak samo dobrze, jak inne:

function parseNumber(val, decimalPlaces) {
    if (decimalPlaces == null) decimalPlaces = 0
    var ret = Number(val).toFixed(decimalPlaces)
    return Number(ret)
}

Ponieważ toFixed () można wywoływać tylko na liczbach i, niestety, zwraca ciąg znaków, wykonuje to całą analizę w obu kierunkach. Możesz przekazać ciąg lub liczbę, a za każdym razem otrzymasz numer! Wywołanie parseNumber (1.49) da ci 1, a parseNumber (1.49,2) da ci 1.50. Tak jak najlepsi z nich!

Aaron Dake
źródło
0

Możesz także użyć .toPrecision()metody i kodu niestandardowego i zawsze zaokrąglać w górę do n-tej cyfry dziesiętnej bez względu na długość części int.

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

Możesz także uczynić go wtyczką dla lepszego wykorzystania.

leo_lo
źródło
-1

Proste jak to.

var rounded_value=Math.round(value * 100) / 100;
Gihan Gamage
źródło
1
Źle. Spróbuj 1.015
Marco Marsala
-2

Znalazłem bardzo prosty sposób, który rozwiązał dla mnie ten problem i można go użyć lub dostosować:

td[row].innerHTML = price.toPrecision(price.toFixed(decimals).length

źródło
-4

100% działa !!! Spróbuj

<html>
     <head>
      <script>
      function replacePonto(){
        var input = document.getElementById('qtd');
        var ponto = input.value.split('.').length;
        var slash = input.value.split('-').length;
        if (ponto > 2)
                input.value=input.value.substr(0,(input.value.length)-1);

        if(slash > 2)
                input.value=input.value.substr(0,(input.value.length)-1);

        input.value=input.value.replace(/[^0-9.-]/,'');

        if (ponto ==2)
	input.value=input.value.substr(0,(input.value.indexOf('.')+3));

if(input.value == '.')
	input.value = "";
              }
      </script>
      </head>
      <body>
         <input type="text" id="qtd" maxlength="10" style="width:140px" onkeyup="return replacePonto()">
      </body>
    </html>

JONAS MAGALHAES DOS SANTOS
źródło
Witamy w SO. Przeczytaj ten poradnik i postępuj zgodnie z wytycznymi, aby odpowiedzieć.
thewaywewere