Javascript: yuvarlanmış bir sayıyı N ondalık basamağa biçimlendirme


104

JavaScript'te, bir sayıyı N ondalık basamağa yuvarlamanın tipik yolu şuna benzer:

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

Ancak , ben her zaman N ondalık basamağa yuvarlamak isterken, bu yaklaşım en fazla N ondalık basamağa yuvarlayacaktır. Örneğin "2.0", "2" ye yuvarlanır.

Herhangi bir fikir?


9
normalde, toFixed()( developer.mozilla.org/En/Core_JavaScript_1.5_Reference/… ) kullanabilirsiniz , ancak IE'de hatalı: stackoverflow.com/questions/661562/… ; kendi versiyonunuzu yazmanız gerekecek ...
Christoph

1
@hoju - belki de kabul edilen cevabı değiştirin - David'in cevabı IE8 + için doğrudur, ancak kabul edilen cevap tüm tarayıcılarda bazı ciddi hatalar içerir.
robocat

@robocat: Ciddi misin?
Guffa

Yanıtlar:


25

Bu bir yuvarlama sorunu değil, bu bir görüntü sorunu. Bir sayı, önemli basamaklar hakkında bilgi içermez; 2 değeri 2.0000000000000 ile aynıdır. Yuvarlanan değeri bir dizeye dönüştürdüğünüzde, belirli sayıda basamak görüntülemesini sağlarsınız.

Sayıdan sonra sıfır ekleyebilirsiniz, örneğin:

var s = number.toString();
if (s.indexOf('.') == -1) s += '.';
while (s.length < s.indexOf('.') + 4) s += '0';

(Bunun, istemcinin bölgesel ayarlarının ondalık ayırıcı olarak nokta kullandığını varsaydığını, kodun diğer ayarlar için çalışması için biraz daha çalışma gerektirdiğini unutmayın.)


3
toFixed hatalı ... örneğin ondalık: 1.02449999998 dec.toFixed (4) => 1.0244 yaparsanız. Bunun yerine 1.0245 olmalıydı.
Bat_Programmer

2
@deepeshk Peki toFixed(), yuvarlamadan sonra, sonunda ondalık sayıları doldurmak için kullanmanın sorunu ne olur ?
pauloya

10
@deepeshk hangi tarayıcıda? Sadece Chrome 17'de denedim ve 1.02449999998.toFixed(4)doğru şekilde geri dönüyor 1.0245.
Matt Ball

3
@MarkTomlin: O zaman bir sayı yerine bir dizeniz var gibi görünüyor.
Guffa

1
.toFixed () modern tarayıcılarda harika çalışıyor (Chrome, Firefox, IE11, IE8'i test ettim). @Bat_Programmer - lütfen hangisi olduğunu açıklayın o hata var tarayıcılar.
robocat

243

Bence burada verilenlerin hepsine daha basit bir yaklaşım var ve bu yöntem Number.toFixed()zaten JavaScript'te uygulanıyor.

basitçe yazın:

var myNumber = 2;

myNumber.toFixed(2); //returns "2.00"
myNumber.toFixed(1); //returns "2.0"

vb...


Nerede bahsediliyor hoju? Diğer yanıtları inceledim ve toFixed işlevinin hatalı olduğunu bildiren birini bulamadım. Teşekkürler
David

@David: Örneğin cevaba yapılan bir yorumda bahsediliyor.
Guffa

13
dikkat: toFixed()bir dize döndürür.
Jordan Arseno

2
@JordanArseno bu, parseInt (myNumber.toFixed (intVar)) kullanılarak düzeltilebilir; bir tamsayı değeri veya parseFloat (myNumber.toFixed (floatVar)) döndürmek için; kullanıcının ondalık basamağı varsa bir kayan nokta döndürmek için.
Stephen Romero

50

Bir yol buldum. Bu, Christoph'un düzeltmeli kodu:

function toFixed(value, precision) {
    var precision = precision || 0,
        power = Math.pow(10, precision),
        absValue = Math.abs(Math.round(value * power)),
        result = (value < 0 ? '-' : '') + String(Math.floor(absValue / power));

    if (precision > 0) {
        var fraction = String(absValue % power),
            padding = new Array(Math.max(precision - fraction.length, 0) + 1).join('0');
        result += '.' + padding + fraction;
    }
    return result;
}

"+ 1" i neden eklediğimi merak ediyorsanız, burada bir dizi kurucusu kullanarak bir karakteri tekrar etmenin ayrıntılarını okuyun .


708.3333333333333 değerini 2 veya 3 hassasiyetle geçirmek benim için 708,00 dönüş değeri ile sonuçlanır. Buna 2 ondalık basamak için ihtiyacım var, Chrome ve IE 9.toFixed (2) ihtiyaçlarımı karşıladı.
alan

bu yaygın bir yol değildir, örneğin, toFixed (16.775, 2) return 16.77. Sayıyı String'e dönüştürdükten sonra dönüştürmek tek yoldur.
hiway

2
Bu yöntemde bir hata var: toFixed (-0.1111, 2) 0.11 döndürür, yani eksi işareti kaybolur.
Matt

Sonunda parseFloat (sonuç) eklemem dışında harika çalışıyor. Düzenlemeye değer.
Artur Barseghyan

16

Bir şeyler yapmanın her zaman daha iyi bir yolu vardır.

var number = 51.93999999999761;

Dört basamaklı kesinlik elde etmek istiyorum: 51,94

sadece yap:

number.toPrecision(4);

sonuç şöyle olacaktır: 51.94


2
Ya 100 eklerseniz? Number.toPrecision (5) olarak değiştirmeniz gerekiyor mu?
JohnnyBizzle

2
Evet. 31.939383.toPrecision (4)> "31.94" / 131.939383.toPrecision (4)> "131.9"
ReSpawN

6

PHP Benzeri Yuvarlama Yöntemi

Aşağıdaki kod, kendi Math.round sürümünüzü hassas bir parametre alan kendi ad alanınıza eklemek için kullanılabilir. Yukarıdaki örnekteki Ondalık yuvarlamadan farklı olarak, bu, dizelere ve dizelerden dönüştürme yapmaz ve kesinlik parametresi PHP ve Excel ile aynı şekilde çalışır; burada pozitif 1, 1 ondalık basamağa yuvarlanır ve -1, onlara yuvarlanır.

var myNamespace = {};
myNamespace.round = function(number, precision) {
    var factor = Math.pow(10, precision);
    var tempNumber = number * factor;
    var roundedTempNumber = Math.round(tempNumber);
    return roundedTempNumber / factor;
};

myNamespace.round(1234.5678, 1); // 1234.6
myNamespace.round(1234.5678, -1); // 1230

dan ) (Math.Round Mozilla Geliştirici referans


2

Umarım çalışan kod (çok fazla test yapmadı):

function toFixed(value, precision) {
    var precision = precision || 0,
        neg = value < 0,
        power = Math.pow(10, precision),
        value = Math.round(value * power),
        integral = String((neg ? Math.ceil : Math.floor)(value / power)),
        fraction = String((neg ? -value : value) % power),
        padding = new Array(Math.max(precision - fraction.length, 0) + 1).join('0');

    return precision ? integral + '.' +  padding + fraction : integral;
}

Kodunuzda bir hata var. Fixed (2.01, 4) denedim ve "2.100" sonucunu aldım. Düzeltmenin bir yolunu bulursam, bu soruya bir cevap olarak göndereceğim.
Elias Zamaria

@ mikez302: dolgu hesaplaması bir farkla iptal edildi; şimdi çalışmalı, ancak hala bozuksa beni tekrar
Christoph

Çok ilginç. Bu işlevi firefox 17'de açık ateş böceği konsolu ile çalıştırdığımda, js sonsuz bir döngüye yakalanmış gibi tüm tarayıcıyı donduruyor. Çıktıyı console.log yapmasam bile. Firebug'ı etkinleştirmediysem, hata oluşmaz.
SublymeRick

1
Güncelleme, Chrome'da çalıştırdım ve şunu elde ediyorum: Yakalanmamış RangeError: toFixed işlev çağrısına göre maksimum çağrı yığını boyutu aşıldı.
SublymeRick

@SublymeRick: Bunun neden olduğu hakkında hiçbir fikrim yok; karanlıkta çekildi: işlevi yeniden adlandırmayı deneyin ...
Christoph

2

Bence aşağıdaki işlev yardımcı olabilir

function roundOff(value,round) {
   return (parseInt(value * (10 ** (round + 1))) - parseInt(value * (10 ** round)) * 10) > 4 ? (((parseFloat(parseInt((value + parseFloat(1 / (10 ** round))) * (10 ** round))))) / (10 ** round)) : (parseFloat(parseInt(value * (10 ** round))) / ( 10 ** round));
}

kullanım: roundOff(600.23458,2);dönecek600.23


2

Bu, N basamağa yuvarlamak için çalışır (yalnızca N basamağa kesmek istiyorsanız Math.round çağrısını kaldırın ve Math.trunc birini kullanın):

function roundN(value, digits) {
   var tenToN = 10 ** digits;
   return /*Math.trunc*/(Math.round(value * tenToN)) / tenToN;
}

Geçmişte veri işleme E-Slate bileşenlerini yazarken Java'da böyle bir mantığa başvurmak zorunda kaldım . Bu, 0'a defalarca 0.1 eklemenin beklenmedik bir şekilde uzun bir ondalık kısımla sonuçlanacağını öğrendiğimden beri (bu, kayan nokta aritmetiklerinden kaynaklanmaktadır).

Her zaman 2 ondalık basamağı gösteren Biçim numarası'ndaki bir kullanıcı yorumu bu tekniği ölçeklendirmeyi çağırır.

Bazıları beklendiği gibi yuvarlanmayan durumlar olduğunu ve bunun yerine http://www.jacklmoore.com/notes/rounding-in-javascript/ adresinde bunun önerildiğinden bahsediyor :

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

btw, POSITS gelecekteki h / w mimarileri için umut vaat ediyor: nextplatform.com/2019/07/08/…
George Birbilis

-2

Yuvarlamayı gerçekten umursamıyorsanız, bir Sabit (x) ekleyin ve ardından gerekirse sondaki 0ları ve noktayı kaldırın. Hızlı bir çözüm değil.

function format(value, decimals) {
    if (value) {
        value = value.toFixed(decimals);            
    } else {
        value = "0";
    }
    if (value.indexOf(".") < 0) { value += "."; }
    var dotIdx = value.indexOf(".");
    while (value.length - dotIdx <= decimals) { value += "0"; } // add 0's

    return value;
}

Beklediğim halde denedim format(1.2, 5)ve aldım . 1.21.20000
Elias Zamaria

Üzgünüm @EliasZamaria, ilk başta anlamadım. Gönderiyi düzenledim. Değer tanımsız olduğunda "0.0000" döneceğini unutmayın.
Juan Carrey
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.