Làm thế nào để định dạng một float trong javascript?


427

Trong JavaScript, khi chuyển đổi từ dấu phẩy thành chuỗi, làm thế nào tôi có thể nhận được chỉ 2 chữ số sau dấu thập phân? Ví dụ: 0,34 thay vì 0,3445434.


16
Chỉ cần chọn một số nit: bạn có muốn 'chặt' tất cả trừ hai chữ số đầu tiên hay bạn muốn làm tròn đến hai chữ số?
xtofl

Câu trả lời:


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

Các chi tiết cụ thể , trong trường hợp mã không tự giải thích.

chỉnh sửa: ... hoặc chỉ sử dụng toFixed, theo đề xuất của Tim Büthe . Quên cái đó đi, cảm ơn (và một upvote) để nhắc nhở :)


1
Tôi đã sử dụng cái này trong thư viện "Highchart" nơi nó không chấp nhận các giá trị chuỗi do đó toFixed không hoạt động với tôi, Math.round đã giải quyết vấn đề của tôi, cảm ơn
Swapnil Chincholkar

4
toFixed()sẽ bắt chước những gì giống như printf()trong C. Tuy nhiên, toFixed()Math.round()sẽ xử lý làm tròn khác nhau. Trong trường hợp này, toFixed()sẽ có cùng loại hiệu ứng Math.floor()(với điều kiện bạn nhân số gốc với 10 ^ n trước đó và gọi toFixed()bằng n chữ số). "Tính chính xác" của câu trả lời phụ thuộc rất nhiều vào những gì OP muốn ở đây và cả hai đều "chính xác" theo cách riêng của họ.
DDPWNAGE

838

Có chức năng để làm tròn số. Ví dụ:

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

sẽ in 5.04.

EDIT: Fiddle


7
Tuy nhiên, tôi khuyên bạn không nên sử dụng print () trong trình duyệt
cobbal

70
Hãy cẩn thận về điều này, toFixed () trả về một chuỗi: var x = 5.036432346; var y = x.toFixed(2) + 100; ysẽ bằng nhau"5.03100"
Vlad

5
Xin lưu ý rằng (1e100) .toFixed (2) === "1e + 100"
qbolec

7
Ngoài ra, hãy cẩn thận của làm tròn không phù hợp: (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)...
Skippy le Grand Gourou

3
Nếu bạn tìm kiếm tương đương với toFixed nhưng với làm tròn nhất quán, hãy sử dụng toLocaleString: (0.345) .toLocaleString ('en-EN', {minimFractionDigits: 2, MaximumFractionDigits: 2})
fred727

185

Cẩn thận khi sử dụng toFixed():

Đầu tiên, làm tròn số được thực hiện bằng cách sử dụng biểu diễn nhị phân của số, điều này có thể dẫn đến hành vi không mong muốn. Ví dụ

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

thay vì '0.6'.

Thứ hai, có một lỗi IE với toFixed(). Trong IE (ít nhất là tới phiên bản 7, không kiểm tra IE8), điều sau đây đúng:

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

Có thể là một ý tưởng tốt để làm theo đề xuất của kkyy hoặc sử dụng toFixed()chức năng tùy chỉnh , ví dụ:

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

Vâng, điều này có thể rất quan trọng khi tạo mã để dự đoán giá. Cảm ơn! +1
Fabio Milheiro

10
Tôi sẽ đề nghị thêm .toFixed()phương thức gốc trong giá trị trả về, sẽ thêm số lượng chính xác cần thiết, ví dụ: return (Math.round(value * power) / power).toFixed(precision);và cũng trả về giá trị dưới dạng chuỗi. Mặt khác, độ chính xác của 20 bị bỏ qua cho các số thập phân nhỏ hơn
William Joss Crowcroft

3
Một lưu ý liên quan đến toFixed: lưu ý rằng việc tăng độ chính xác có thể mang lại kết quả không mong muốn:, (1.2).toFixed(16) === "1.2000000000000000"trong khi (1.2).toFixed(17) === "1.19999999999999996"(trong Firefox / Chrome; trong IE8, cái sau không giữ được do độ chính xác thấp hơn mà IE8 có thể cung cấp trong nội bộ).
jakub.g

2
Xin lưu ý rằng thậm chí (0.598).toFixed(2)không sản xuất 0.6. Nó tạo ra 0.60:)
qbolec

1
Ngoài ra, hãy cẩn thận với làm tròn không nhất quán : (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2).
Skippy le Grand Gourou

36

Một vấn đề nữa cần lưu ý, đó là toFixed()có thể tạo ra các số không cần thiết ở cuối số. Ví dụ:

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

Ý tưởng là để làm sạch đầu ra bằng cách sử dụng RegExp:

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

Các RegExpsố không khớp với các số 0 ở cuối (và tùy ý là dấu thập phân) để đảm bảo nó cũng tốt cho các số nguyên.

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 = function (decimals) {return this.toFixed (decimals) .replace (/ \.? 0 * $ /, ""); }
Luc Bloom

Điều này nên được đánh giá, các số 0 ở cuối rất khó chịu, tôi đã tìm chính xác cho giải pháp này, gj.
ex Tư

1
Các số 0 lưu trữ có thể gây khó chịu, nhưng đây chính xác là những gì tên phương thức "toFixed" hứa hẹn sẽ làm;)
ksadowski

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

Math.round (1.015 * 100) / 100 cho 1.01 trong khi chúng ta mong đợi nó là 1.02?
gaurav5430

6

Có một vấn đề với tất cả những giải pháp nổi xung quanh bằng cách sử dụng bội số. Cả hai giải pháp của kkyy và Christoph đều sai.

Vui lòng kiểm tra mã của bạn cho số 551.175 với 2 chữ số thập phân - nó sẽ làm tròn thành 551,17 trong khi đó sẽ là 551,18 ! Nhưng nếu bạn kiểm tra cho ex. 451.175 sẽ ổn thôi - 451,18. Vì vậy, thật khó để phát hiện ra lỗi này ngay từ cái nhìn đầu tiên.

Vấn đề là nhân lên: thử 551.175 * 100 = 55117.49999999999 (up!)

Vì vậy, ý tưởng của tôi là xử lý nó với toFixed () trước khi sử dụng Math.round ();

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

1
Đó là vấn đề với số học trong js: (551.175 * 10 * 10)! == (551.175 * 100). Bạn phải sử dụng số thập phân để di chuyển dấu phẩy cho kết quả thập phân không thực.
Kir Kanos

+1 để nhận thấy điều này, tuy nhiên toFixedcũng bị ảnh hưởng - (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)Phương pháp nào được sử dụng, tốt hơn là thêm một epsilon trước khi làm tròn.
Skippy le Grand Gourou

5

Chìa khóa ở đây tôi đoán là làm tròn chính xác trước, sau đó bạn có thể chuyển đổi nó thành Chuỗi.

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

Bây giờ bạn có thể định dạng giá trị này một cách an toàn với toFixed (p). Vì vậy, với trường hợp cụ thể của bạn:

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

3

Nếu bạn muốn chuỗi không có vòng, bạn có thể sử dụng RegEx này (có thể không phải là cách hiệu quả nhất ... nhưng thực sự dễ dàng)

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

câu trả lời tuyệt vời ngoại trừ việc bạn thiếu dấu chấm phẩy (Không, trong dấu chấm phẩy es6 không bị lỗi thời và chúng tôi vẫn phải sử dụng chúng trong một số trường hợp). Tôi cũng phải chỉnh sửa hàng cuối cùng thành: return float_part ? int_part+'.'+float_part : int_part;nếu không, nếu bạn vượt qua Integer, nó sẽ trả về số có dấu chấm ở cuối (ví dụ đầu vào : 2100, đầu ra 2100.:)
Kuba imonovský

0

Có lẽ bạn cũng sẽ muốn phân tách thập phân? Đây là một chức năng tôi vừa thực hiện:

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

Không có cách nào để tránh làm tròn không nhất quán cho giá với x.xx5 là giá trị thực bằng cách sử dụng phép nhân hoặc chia. Nếu bạn cần tính toán giá chính xác phía khách hàng, bạn nên giữ tất cả số tiền tính bằng xu. Điều này là do bản chất của biểu diễn bên trong của các giá trị số trong JavaScript. Lưu ý rằng Excel bị các vấn đề tương tự, vì vậy hầu hết mọi người sẽ không nhận thấy các lỗi nhỏ do hiện tượng này gây ra. Tuy nhiên, lỗi có thể tích lũy bất cứ khi nào bạn cộng nhiều giá trị được tính toán, có toàn bộ lý thuyết xung quanh vấn đề này liên quan đến thứ tự tính toán và các phương pháp khác để giảm thiểu lỗi trong kết quả cuối cùng. Để nhấn mạnh về các vấn đề với giá trị thập phân, xin lưu ý rằng 0,1 + 0,2 không chính xác bằng 0,3 trong JavaScript, trong khi 1 + 2 bằng 3.


giải pháp sẽ là tách toàn bộ phần và phần thập phân, và biểu diễn chúng dưới dạng số nguyên trong cơ sở 10, thay vì sử dụng phao, ở đây nó hoạt động mà không gặp vấn đề gì với PrettyPrint, nhưng nói chung, bạn phải chọn giữa cơ sở và phần khác, một sự phản hồi cho số thực và số khác, mỗi số có vấn đề của nó
tái hợp

"Excel bị các vấn đề tương tự". nguồn nào?
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

Tôi sử dụng mã này để định dạng nổi. Nó dựa trên toPrecision()nhưng nó tước các số không cần thiết. Tôi sẽ hoan nghênh các đề xuất về cách đơn giản hóa regex.

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

Ví dụ sử dụng:

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>');
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.