Javascript: định dạng một số làm tròn thành N số thập phân


104

trong JavaScript, cách thông thường để làm tròn một số đến N chữ số thập phân là như sau:

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

Tuy nhiên, phương pháp này sẽ làm tròn đến tối đa N chữ số thập phân trong khi tôi muốn luôn tròn đến N chữ số thập phân. Ví dụ: "2.0" sẽ được làm tròn thành "2".

Bất kỳ ý tưởng?


9
bình thường, bạn có thể sử dụng toFixed()( developer.mozilla.org/En/Core_JavaScript_1.5_Reference/… ), nhưng nó có lỗi trong IE: stackoverflow.com/questions/661562/… ; bạn sẽ phải viết phiên bản của riêng mình ...
Christoph

1
@hoju - có lẽ câu trả lời được chấp nhận thay đổi - câu trả lời của David đúng cho IE8 +, trong khi câu trả lời được chấp nhận có một số lỗi nghiêm trọng trên tất cả các trình duyệt.
robocat

@robocat: Bạn có nghiêm túc không?
Guffa

Câu trả lời:


25

Đó không phải là vấn đề làm tròn, đó là vấn đề hiển thị. Một số không chứa thông tin về các chữ số có nghĩa; giá trị 2 giống như 2,0000000000000. Đó là khi bạn chuyển giá trị làm tròn thành một chuỗi mà bạn đã làm cho nó hiển thị một số chữ số nhất định.

Bạn chỉ có thể thêm các số 0 vào sau số, giống như:

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

(Lưu ý rằng điều này giả định rằng cài đặt khu vực của máy khách sử dụng dấu chấm làm dấu phân cách thập phân, mã cần thêm một số công việc để hoạt động cho các cài đặt khác.)


3
toFixed bị lỗi..ví dụ: số thập phân: 1.02449999998 nếu bạn làm dec.toFixed (4) => 1.0244. Thay vào đó nó phải là 1.0245.
Bat_Programmer,

2
@deepeshk Nhưng sẽ có vấn đề gì với việc sử dụng toFixed()để đệm số thập phân vào cuối, sau khi làm tròn?
pauloya

10
@deepeshk trong trình duyệt nào? Chỉ cần thử nó trong Chrome 17 và 1.02449999998.toFixed(4)trả về chính xác 1.0245.
Matt Ball

3
@MarkTomlin: Sau đó, có vẻ như bạn có một chuỗi thay vì một số.
Guffa

1
.toFixed () hoạt động xuất sắc trong các trình duyệt hiện đại (tôi đã thử nghiệm Chrome, Firefox, IE11, IE8). @Bat_Programmer - vui lòng làm rõ trình duyệt bạn nghĩ có lỗi đó.
robocat

243

Tôi nghĩ rằng có một cách tiếp cận đơn giản hơn cho tất cả những gì được đưa ra ở đây và là phương pháp Number.toFixed()đã được triển khai trong JavaScript.

chỉ cần viết:

var myNumber = 2;

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

Vân vân...


Được đề cập ở đâu, hoju? Tôi đã xem xét các câu trả lời khác và tôi không tìm thấy bất kỳ ai báo cáo rằng chức năng toFixed bị lỗi. Cảm ơn
David

@David: Ví dụ: điều đó được đề cập trong nhận xét cho câu trả lời.
Guffa

13
thận trọng: toFixed()trả về một chuỗi.
Jordan Arseno

2
@JordanArseno điều này có thể được khắc phục bằng cách sử dụng parseInt (myNumber.toFixed (intVar)); để trả về một giá trị số nguyên hoặc parseFloat (myNumber.toFixed (floatVar)); để trả về một số thực nếu người dùng có vị trí thập phân.
Stephen Romero

50

Tôi tìm thấy một cách. Đây là mã của Christoph với một bản sửa lỗi:

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

Đọc chi tiết về việc lặp lại một ký tự bằng cách sử dụng hàm tạo mảng tại đây nếu bạn muốn biết tại sao tôi lại thêm dấu "+ 1".


Chuyển giá trị 708.3333333333333 với độ chính xác 2 hoặc 3 dẫn đến giá trị trả về là 708,00 cho tôi. Tôi cần cái này cho 2 chữ số thập phân, trong Chrome và IE 9 .toFixed (2) đã đáp ứng nhu cầu của tôi.
alan

đây không phải là cách phổ biến, ví dụ: toFixed (16.775, 2) trả về 16.77. Chuyển đổi số thành Chuỗi sau đó chuyển đổi là cách duy nhất.
hiway

2
Có một lỗi với phương pháp này: toFixed (-0.1111, 2) trả về 0.11, tức là dấu âm bị mất.
Matt

Hoạt động tuyệt vời, ngoại trừ việc tôi đã thêm parseFloat (kết quả) vào cuối. Đáng để chỉnh sửa.
Artur Barseghyan

16

Luôn luôn có một cách tốt hơn để làm mọi việc.

var number = 51.93999999999761;

Tôi muốn nhận được độ chính xác bốn chữ số: 51,94

cứ làm đi:

number.toPrecision(4);

kết quả sẽ là: 51,94


2
Và nếu bạn thêm 100? Bạn có cần thay đổi nó thành number.toPre chì (5) không?
JohnnyBizzle

2
Đúng. 31.939383.toPre precision (4)> "31,94" / 131.939383.toPre precision (4)> "131,9"
ReSpawN

6

Phương pháp làm tròn giống PHP

Mã bên dưới có thể được sử dụng để thêm phiên bản Math.round của riêng bạn vào không gian tên của riêng bạn, vùng này có tham số chính xác. Không giống như làm tròn số thập phân trong ví dụ trên, điều này không thực hiện chuyển đổi thành và từ chuỗi và tham số chính xác hoạt động giống như PHP và Excel, theo đó số dương 1 sẽ làm tròn thành 1 chữ số thập phân và -1 sẽ làm tròn đến hàng chục.

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

từ tài liệu tham khảo dành cho Nhà phát triển Mozilla cho Math.round ()


2

Hy vọng rằng mã làm việc (không thực hiện nhiều thử nghiệm):

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

Mã của bạn có một lỗi. Tôi đã thử sửa lại (2.01, 4) và nhận được kết quả là "2.100". Nếu tôi tìm được cách khắc phục nó, tôi sẽ đăng nó như một câu trả lời cho câu hỏi này.
Elias Zamaria

@ mikez302: tính toán phần đệm đã bị tắt; sẽ hoạt động ngay bây giờ, nhưng hãy thông báo lỗi cho tôi một lần nữa nếu nó vẫn bị hỏng ...
Christoph

Rất lạ. Khi tôi chạy fuction này với bảng điều khiển firebug mở trong firefox 17, nó đóng băng toàn bộ trình duyệt giống như js bị mắc vào một vòng lặp vô tận. Ngay cả khi tôi không console.log đầu ra. Nếu tôi chưa kích hoạt firebug thì lỗi không xảy ra.
SublymeRick

1
Cập nhật, tôi đã chạy nó trong chrome và tôi nhận được: Uncaught RangeError: Đã vượt quá kích thước ngăn xếp lệnh gọi tối đa liên quan đến lệnh gọi hàm toFixed.
SublymeRick

@SublymeRick: Tôi không biết tại sao điều này lại xảy ra; shot trong bóng tối: cố gắng đổi tên chức năng ...
Christoph

2

Tôi nghĩ rằng chức năng dưới đây có thể giúp

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

sử dụng: roundOff(600.23458,2);sẽ trở lại600.23


2

Điều này hoạt động để làm tròn đến N chữ số (nếu bạn chỉ muốn cắt ngắn đến N chữ số, hãy xóa lệnh gọi Math.round và sử dụng lệnh Math.trunc một):

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

Trước đây tôi đã phải sử dụng đến logic như vậy ở Java khi tôi làm tác giả của các thành phần E-Slate thao tác dữ liệu . Đó là vì tôi đã phát hiện ra rằng thêm 0,1 nhiều lần với 0, bạn sẽ kết thúc với một số phần thập phân dài bất ngờ (điều này là do số học dấu phẩy động).

Một nhận xét của người dùng tại Định dạng số để luôn hiển thị 2 chữ số thập phân gọi kỹ thuật này là chia tỷ lệ.

Một số đề cập rằng có những trường hợp không tròn như mong đợi và tại http://www.jacklmoore.com/notes/rounding-in-javascript/ điều này được đề xuất thay thế:

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

btw, POSITS đầy hứa hẹn cho các kiến ​​trúc h / w trong tương lai: nextplatform.com/2019/07/08/…
George Birbilis

-2

Nếu bạn không thực sự quan tâm đến việc làm tròn, chỉ cần thêm một toFixed (x) và sau đó xóa các số 0 ở cuối và dấu chấm nếu cần. Nó không phải là một giải pháp nhanh chóng.

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

Tôi đã thử format(1.2, 5)và đạt được 1.2, trong khi tôi mong đợi 1.20000.
Elias Zamaria vào

Xin lỗi @EliasZamaria, lúc đầu tôi không hiểu. Tôi đã sửa bài. Chỉ cần lưu ý rằng nó sẽ trả về "0,0000" khi giá trị không được xác định.
Juan Carrey
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.