Javascript'te bir şamandıra nasıl biçimlendirilir?


427

JavaScript'te, kayan noktadan dizeye dönüştürürken, ondalık noktadan sonra nasıl yalnızca 2 basamak alabilirim? Örneğin, 0.3445434 yerine 0.34.


16
Sadece bir miktar nit toplama: ilk iki rakam hariç hepsini kesmek mi istiyorsunuz yoksa iki basamağa mı yuvarlamak istiyorsunuz?
xtofl

Yanıtlar:


232
var result = Math.round(original*100)/100;

Özelliklerini , durumda kod kendini açıklayıcı değildir.

edit: ... ya da sadece kullanın toFixed, Tim Büthe tarafından önerildiği gibi . Bunu unuttum, hatırlatma için teşekkürler (ve bir yukarı oy) :)


1
Ben bu yüzden toFixed benim için işe yaramadı, dize değerleri kabul etmez kitaplık "Highchart" kullanıyordum, Math.round benim sorun çözdü, teşekkürler
Swapnil Chincholkar

4
toFixed()printf()Ancak C'de nasıl bir şey olduğunu taklit eder toFixed()ve Math.round()yuvarlamayı farklı şekilde ele alır. Bu durumda, toFixed()aynı tür bir etkiye sahip Math.floor()olacaktır (orijinali önceden 10 ^ n ile çarptığınız ve toFixed()n basamakla çağırdığınız kabul edilir). Cevabın "doğruluğu" OP'nin burada ne istediğine çok bağlıdır ve her ikisi de kendi yollarıyla "doğrudur".
DDPWNAGE

838

Sayıları yuvarlamak için işlevler vardır. Örneğin:

var x = 5.0364342423;
print(x.toFixed(2));

5.04 yazdıracaktır.

DÜZENLEME: Keman


7
Yine de bir tarayıcıda print () kullanmaya karşı öneriyorum
cobbal

70
Bu konuda dikkatli olun, toFixed () bir dize döndürür: var x = 5.036432346; var y = x.toFixed(2) + 100; yeşit olacak"5.03100"
Vlad

5
Unutmayın (1e100) .toFixed (2) === "1e + 100"
qbolec

7
Ayrıca, tutarsız yuvarlamaya dikkat edin: (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)
Skippy le Grand Gourou

3
ToFixed eşdeğerini ancak tutarlı yuvarlama ile ararsanız, toLocaleString: (0.345) .toLocaleString ('en-EN', {minimumFractionDigits: 2, maximumFractionDigits: 2})
fred727 29:18 '

185

Kullanırken dikkatli olun toFixed():

İlk olarak, sayının yuvarlanması, sayının ikili gösterimi kullanılarak yapılır, bu da beklenmedik davranışlara yol açabilir. Örneğin

(0.595).toFixed(2) === '0.59'

yerine '0.6'.

İkincisi, bir IE hatası var toFixed(). IE'de (en azından sürüm 7, IE8'i kontrol etmedi), aşağıdakiler geçerlidir:

(0.9).toFixed(0) === '0'

Kkyy'nin önerisini takip etmek veya özel bir toFixed()işlev kullanmak iyi bir fikir olabilir , örn.

function toFixed(value, precision) {
    var power = Math.pow(10, precision || 0);
    return String(Math.round(value * power) / power);
}

Evet, fiyatları tahmin etmek için kod oluştururken bu çok önemli olabilir. Teşekkürler! +1
Fabio Milheiro

10
Ben .toFixed()gerekli değer, örneğin ekleyecek dönüş değeri, yerel yöntem ekleme öneririz : return (Math.round(value * power) / power).toFixed(precision);ve ayrıca değeri bir dize olarak döndürür. Aksi takdirde, daha küçük ondalık sayılar için 20'nin hassasiyeti yok sayılır
William Joss Crowcroft

3
İlişkin bir not toFixed: hassasiyet artan beklenmeyen sonuçlara yol açabilir o notu (1.2).toFixed(16) === "1.2000000000000000"iken (1.2).toFixed(17) === "1.19999999999999996"(Firefox / Chrome'da; IE8'de ikincisi IE8 içten sunabileceği hassas düşmesi nedeniyle tutmadığı).
jakub.g

2
Unutmayın bile (0.598).toFixed(2)üretmez 0.6. Ürettiği 0.60:)
qbolec

1
Ayrıca, inconstistent yuvarlama dikkat: (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2).
Skippy le Grand Gourou

36

Dikkat edilmesi gereken bir başka sorun da toFixed(), sayının sonunda gereksiz sıfırlar üretebilmesidir. Örneğin:

var x=(23-7.37)
x
15.629999999999999
x.toFixed(6)
"15.630000"

Fikir, çıktıyı aşağıdakileri kullanarak temizlemektir RegExp:

function humanize(x){
  return x.toFixed(6).replace(/\.?0*$/,'');
}

RegExpEmin tamsayılar için iyi yanı görünüyor yapmak için sondaki sıfırları (ve isteğe ondalık noktayı) eşleşir.

humanize(23-7.37)
"15.63"
humanize(1200)
"1200"
humanize(1200.03)
"1200.03"
humanize(3/4)
"0.75"
humanize(4/3)
"1.333333"

Number.prototype.minFixed = işlev (ondalıklar) {bunu döndür. ToFixed (ondalıklar) .replace (/ \.? 0 * $ /, ""); }
Luc Bloom

Bu kabul edilmelidir, sondaki sıfırlar sinir bozucu, tam olarak bu çözümü arıyordum, gj.
exoslav

1
Sondaki sıfırlar sinir bozucu olabilir, ancak "toFixed" yöntem adının tam olarak bunu yapmayı vaat ettiği
şeydir

11
var x = 0.3445434
x = Math.round (x*100) / 100 // this will make nice rounding

Math.round (1.015 * 100) / 100, 1.01 verirken 1.02 olmasını bekler miyiz?
gaurav5430

6

Bu çözümlerin çarpanları kullanarak yüzdüğü bir sorun var. Hem kkyy hem de Christoph'un çözümleri ne yazık ki yanlış.

Lütfen kodunuzu 2 ondalık basamakla 551.175 sayısı için test edin - 551.18 olması gerekirken 551.17'ye yuvarlanır ! Ama eski için test ederseniz. 451.175 iyi olacak - 451.18. Bu yüzden bu hatayı ilk bakışta tespit etmek zor.

Sorun çarpmayla ilgili: 551.175 * 100 = 55117.49999999999 (ups!)

Benim fikrim Math.round () kullanmadan önce toFixed () ile tedavi etmek;

function roundFix(number, precision)
{
    var multi = Math.pow(10, precision);
    return Math.round( (number * multi).toFixed(precision + 1) ) / multi;
}

1
Js'deki aritmetik ile ilgili sorun budur: (551.175 * 10 * 10)! == (551.175 * 100). Gerçek ondalık olmayan sonuçlar için virgül taşımak için ondalık artışları kullanmanız gerekir.
Kir Kanos

Ancak bunu fark ettiğiniz için +1 toFixedde etkilenir - (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)… Hangi yöntem kullanılırsa kullanılsın, yuvarlamadan önce bir epsilon ekleyin.
Skippy le Grand Gourou

5

Buradaki anahtar, önce doğru şekilde yuvarlamaktır, daha sonra String'e dönüştürebilirsiniz.

function roundOf(n, p) {
    const n1 = n * Math.pow(10, p + 1);
    const n2 = Math.floor(n1 / 10);
    if (n1 >= (n2 * 10 + 5)) {
        return (n2 + 1) / Math.pow(10, p);
    }
    return n2 / Math.pow(10, p);
}

// All edge cases listed in this thread
roundOf(95.345, 2); // 95.35
roundOf(95.344, 2); // 95.34
roundOf(5.0364342423, 2); // 5.04
roundOf(0.595, 2); // 0.60
roundOf(0.335, 2); // 0.34
roundOf(0.345, 2); // 0.35
roundOf(551.175, 2); // 551.18
roundOf(0.3445434, 2); // 0.34

Artık bu değeri toFixed (p) ile güvenle biçimlendirebilirsiniz. Yani özel durumunuzla:

roundOf(0.3445434, 2).toFixed(2); // 0.34

3

Dize tur olmadan istiyorsanız bu RegEx'i kullanabilirsiniz (belki de en etkili yol değildir ... ama gerçekten kolaydır)

(2.34567778).toString().match(/\d+\.\d{2}/)[0]
// '2.34'

1
function trimNumber(num, len) {
  const modulu_one = 1;
  const start_numbers_float=2;
  var int_part = Math.trunc(num);
  var float_part = String(num % modulu_one);
      float_part = float_part.slice(start_numbers_float, start_numbers_float+len);
  return int_part+'.'+float_part;
}

noktalı virgül eksik olmanız dışında harika bir yanıt (Hayır, es6'da noktalı virgül kullanılmıyor ve yine de bazı durumlarda kullanmamız gerekiyor). Ben düzenleme son satırı da vardı: return float_part ? int_part+'.'+float_part : int_part;Eğer Tamsayı geçti aksi takdirde, bu sonunda bir nokta ile sayı döndürdü (örnek girişi: 2100, çıkış: 2100.)
Kuba Simonovsky

0

Belki de ondalık ayırıcı isteyeceksiniz? İşte yeni yaptığım bir fonksiyon:

function formatFloat(num,casasDec,sepDecimal,sepMilhar) {
    if (num < 0)
    {
        num = -num;
        sinal = -1;
    } else
        sinal = 1;
    var resposta = "";
    var part = "";
    if (num != Math.floor(num)) // decimal values present
    {
        part = Math.round((num-Math.floor(num))*Math.pow(10,casasDec)).toString(); // transforms decimal part into integer (rounded)
        while (part.length < casasDec)
            part = '0'+part;
        if (casasDec > 0)
        {
            resposta = sepDecimal+part;
            num = Math.floor(num);
        } else
            num = Math.round(num);
    } // end of decimal part
    while (num > 0) // integer part
    {
        part = (num - Math.floor(num/1000)*1000).toString(); // part = three less significant digits
        num = Math.floor(num/1000);
        if (num > 0)
            while (part.length < 3) // 123.023.123  if sepMilhar = '.'
                part = '0'+part; // 023
        resposta = part+resposta;
        if (num > 0)
            resposta = sepMilhar+resposta;
    }
    if (sinal < 0)
        resposta = '-'+resposta;
    return resposta;
}

0

X.xx5 olan fiyatların çarpma veya bölme kullanarak gerçek değer olarak tutarsız yuvarlanmasından kaçınmanın bir yolu yoktur. Müşteri tarafında doğru fiyatları hesaplamanız gerekiyorsa, tüm miktarları sent cinsinden tutmalısınız. Bu, JavaScript'teki sayısal değerlerin dahili sunumunun doğasından kaynaklanmaktadır. Excel'in aynı sorunlardan muzdarip olduğuna dikkat edin, bu yüzden çoğu insan bu fenomenin neden olduğu küçük hataları fark etmeyecektir. Bununla birlikte, çok sayıda hesaplanmış değer eklediğinizde hatalar birikebilir, bunun etrafında hesaplamaların sırasını ve nihai sonuçtaki hatayı en aza indirmek için diğer yöntemleri içeren bir teori vardır. Ondalık değerlerle ilgili sorunları vurgulamak için, JavaScript'te 0,1 + 0,2'nin tam olarak 0,3'e eşit olduğunu, 1 + 2'nin 3'e eşit olduğunu lütfen unutmayın.


çözüm, tüm parçayı ve ondalık parçayı ayırmak ve bunları kayan nokta kullanmak yerine taban 10'da tamsayı olarak temsil etmek olacaktır, burada prettyPrint için sorunsuz çalışır, ancak genel olarak bir taban ile diğeri arasında bir seçim yapmanız gerekir. gerçek sayılar ve diğeri, her birinin sorunları var
15:54

"Excel aynı sorunlardan muzdarip". kaynak ?
gaurav5430

0
/** don't spend 5 minutes, use my code **/
function prettyFloat(x,nbDec) { 
    if (!nbDec) nbDec = 100;
    var a = Math.abs(x);
    var e = Math.floor(a);
    var d = Math.round((a-e)*nbDec); if (d == nbDec) { d=0; e++; }
    var signStr = (x<0) ? "-" : " ";
    var decStr = d.toString(); var tmp = 10; while(tmp<nbDec && d*tmp < nbDec) {decStr = "0"+decStr; tmp*=10;}
    var eStr = e.toString();
    return signStr+eStr+"."+decStr;
}

prettyFloat(0);      //  "0.00"
prettyFloat(-1);     // "-1.00"
prettyFloat(-0.999); // "-1.00"
prettyFloat(0.5);    //  "0.50"

0

Bu kodu yüzen biçimlendirmek için kullanın. Tabanlı toPrecision()ama gereksiz sıfırlar çıkarıyor. Normal ifadeyi basitleştirmek için önerilerinizi memnuniyetle karşılarım.

function round(x, n) {
    var exp = Math.pow(10, n);
    return Math.floor(x*exp + 0.5)/exp;
}

Kullanım örneği:

function test(x, n, d) {
    var rounded = rnd(x, d);
    var result = rounded.toPrecision(n);
    result = result.replace(/\.?0*$/, '');
    result = result.replace(/\.?0*e/, 'e');
    result = result.replace('e+', 'e');
    return result;  
}

document.write(test(1.2000e45, 3, 2) + '=' + '1.2e45' + '<br>');
document.write(test(1.2000e+45, 3, 2) + '=' + '1.2e45' + '<br>');
document.write(test(1.2340e45, 3, 2) + '=' + '1.23e45' + '<br>');
document.write(test(1.2350e45, 3, 2) + '=' + '1.24e45' + '<br>');
document.write(test(1.0000, 3, 2) + '=' + '1' + '<br>');
document.write(test(1.0100, 3, 2) + '=' + '1.01' + '<br>');
document.write(test(1.2340, 4, 2) + '=' + '1.23' + '<br>');
document.write(test(1.2350, 4, 2) + '=' + '1.24' + '<br>');
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.