Loại bỏ các số 0 không đáng kể từ một số?


157

Tôi đã bỏ lỡ một lệnh gọi API tiêu chuẩn loại bỏ các số 0 không đáng kể từ một số chưa?

Ví dụ.

var x = 1.234000 // to become 1.234;
var y = 1.234001; // stays 1.234001

Number.toFixed () và Number.toPrecision () không hoàn toàn như những gì tôi đang tìm kiếm.


6
Ừm 1.234000 === 1.234.
Gumbo

5
Phải, nếu bạn cảnh báo (x), nó sẽ bật lên mà không có các số 0 ở cuối
JKirchartz

50
Sau khi làm việc với một số khách hàng, tôi có thể làm chứng rằng mặc dù 1.234000 === 1.234, khách hàng không muốn thấy những số 0 thêm đó nếu họ không cần.
contactmatt

16
Sử dụng parseFloat(n)?
Ông Alien

Đây là giải pháp đơn giản nhất bao gồm tất cả các trường hợp cạnh cho tôi, cảm ơn bạn @ Mr.Alien.
James Perih

Câu trả lời:


140

Nếu bạn chuyển đổi nó thành một chuỗi, nó sẽ không hiển thị bất kỳ số 0 nào, không được lưu trữ trong biến ở vị trí đầu tiên kể từ khi nó được tạo dưới dạng Số, không phải là Chuỗi.

var n = 1.245000
var noZeroes = n.toString() // "1.245" 

6
Tôi đã định đăng một số mã để loại bỏ các số không nhưng giải pháp của Daniel dường như có hiệu quả. Nó thậm chí hoạt động cho các Chuỗi như "1.2345000". ("1.2345000" * 1) .toString (); // trở thành 1.2345
Steven

7
Tất nhiên, nếu var của bạn đã là một chuỗi, bạn phải chuyển đổi nó thành một số đầu tiên và sau đó quay lại
derekcohen

Điều này đã làm việc tuyệt vời. Tôi đã có cùng một vấn đề, chuyển đổi float thành chuỗi và sau đó parseFloat để đưa nó trở lại đúng định dạng, chỉ khi không có các số 0 ở cuối.
Matt West

10
Đây không phải là giải pháp hoàn chỉnh. Nó không làm việc khi bạn có biến với một số lỗi đại diện dấu chấm động, như: var n = 1.245000000000001(giả sử nó là không đáng kể để được đại diện cho người sử dụng)
chiêm tinh gia

7
Có thể tạo ra kết quả bất ngờ cho các số như: 1231111111111111111111111111112122222222222222222222222222222222222222222222222222222. Biểu diễn chuỗi sẽ ở định dạng hàm mũ: 1.23111111111111e + 81
Stas Makutin

226

Tôi đã có một ví dụ tương tự khi tôi muốn sử dụng .toFixed()khi cần thiết, nhưng tôi không muốn phần đệm khi không. Vì vậy, tôi đã kết thúc việc sử dụng parseFloat kết hợp với toFixed.

toFixed mà không cần đệm

parseFloat(n.toFixed(4));

Một lựa chọn khác gần như tương tự
Câu trả lời này có thể giúp quyết định của bạn

Number(n.toFixed(4));

toFixedsẽ làm tròn / đệm số đến một độ dài cụ thể, nhưng cũng chuyển đổi nó thành một chuỗi. Chuyển đổi trở lại thành một loại số sẽ không chỉ giúp số an toàn hơn khi sử dụng một cách hợp lý, mà còn tự động giảm bất kỳ dấu 0 nào. Ví dụ:

var n = "1.234000";
    n = parseFloat(n);
 // n is 1.234 and in number form

Bởi vì ngay cả khi bạn xác định một số có số 0 ở cuối thì chúng vẫn bị bỏ.

var n = 1.23000;
 // n == 1.23;

Lưu ý rằng điều này chỉ hoạt động nếu số thập phân có liên quan bằng hoặc lớn hơn đối số toFixed. Nếu số là ví dụ 1.200000, kết quả của toFixed (3) sẽ là 1.200 và do đó, không có tất cả các số 0 ở cuối sẽ bị xóa.
Leopoldo Sanchot

@LeopoldoSanc Hot Không, điều đó chỉ đúng nếu bạn chỉ sử dụng toFixed, vì nó trả về một chuỗi. Số loại tự động mất số không. Đó là lý do tại sao tôi sử dụng cả hai cùng một lúc.
Gary

@Gary, tôi rút lại nhận xét của mình, tôi đã thấy parseFloat(n).toFixed(4);thay vì câu trả lời thực tế của bạn. Tôi xin lỗi.
Leopoldo Sanchot

2
Tại sao không +(n.toFixed(4))?
Toàn cảnh

3
nâng cao tinh thần! chỉ có một vấn đề với câu trả lời của bạn 0,00000005 được chuyển đổi thành 5e-8 làm thế nào tôi có thể loại bỏ các số 0 không đáng kể mà không gặp vấn đề này, tôi đang làm việc với các số nhỏ như 0,000058000 trong đó các số 0 ở cuối cần phải được gỡ bỏ
PirateApp

29

Lần đầu tiên tôi sử dụng kết hợp câu trả lời của matti-lyra và gary:

r=(+n).toFixed(4).replace(/\.0+$/,'')

Các kết quả:

  • 1234870.98762341: "1234870.9876"
  • 1230009100: "1230009100"
  • 0,0012234: "0,0012"
  • 0.1200234: "0.12"
  • 0,000001231: "0"
  • 0.10001: "0.1000"
  • "asdf": "NaN" (vì vậy không có lỗi thời gian chạy)

Trường hợp hơi có vấn đề là 0.10001. Tôi đã kết thúc bằng phiên bản dài hơn này:

    r = (+n).toFixed(4);
    if (r.match(/\./)) {
      r = r.replace(/\.?0+$/, '');
    }
  • 1234870.98762341: "1234870.9876"
  • 1230009100: "1230009100"
  • 0,0012234: "0,0012"
  • 0.1200234: "0.12"
  • 0,000001231: "0"
  • 0.10001: "0.1"
  • "asdf": "NaN" (vì vậy không có lỗi thời gian chạy)

Cập nhật : Và đây là phiên bản mới hơn của Gary (xem bình luận):

r=(+n).toFixed(4).replace(/([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)/,'$1')

Điều này cho kết quả tương tự như trên.


1
Tôi đã có một giải pháp regex thuần túy mà tôi tin là có hiệu quảtoFixed(4).replace(/([0-9]+(\.[1-9]+)?)(\.?0+$)/,"$1")
Gary

1
Trời ạ! Rõ ràng tôi gần như không giỏi phá vỡ RegExes của mình hơn những người khác. Tôi sẽ không để điều này đánh bại tôi! Tôi đã chạy cái này với tất cả các trường hợp thử nghiệm của bạn cộng với bất kỳ trường hợp nào (hợp lệ) mà tôi có thể nghĩ đến([0-9]+(\.[0-9]+[1-9])?)(\.?0+$)
Gary

1
Regex là để tham lam đôi khi loại bỏ "0" khỏi phần nguyên! :-( Tại sao không chỉ replace(/[,.][1-9]+(0+)/,'')?
Sebastian Sebald

1
Không nản lòng trả lời này.
Charlie

1
@ w00t ơi, xin lỗi, giờ tôi hiểu rồi. Tôi là cách tôi đã thử nghiệm khi tôi thực hiện (xem liên kết ở trên). Bạn không thất bại khi bạn sử dụng toFixed, vì số được đảm bảo có dấu chấm, nhưng nó đã thất bại trong các thử nghiệm của tôi vì tôi muốn regex hoạt động với bất kỳ số nào, kể cả số nguyên không có dấu chấm. Không có toFixed, nó ăn số 0 ở cuối. Lỗi của tôi.
geekley

21

Các toFixedphương pháp sẽ làm tròn thích hợp nếu cần thiết. Nó cũng sẽ thêm các số 0 ở cuối, không phải lúc nào cũng lý tưởng.

(4.55555).toFixed(2);
//-> "4.56"

(4).toFixed(2);
//-> "4.00"

Nếu bạn bỏ giá trị trả về cho một số, các số 0 đó sẽ bị loại bỏ. Đây là một cách tiếp cận đơn giản hơn so với làm toán tròn hoặc cắt ngắn của riêng bạn.

+(4.55555).toFixed(2);
//-> 4.56

+(4).toFixed(2);
//-> 4

1
khó khăn, nhưng chính xác những gì tôi đã tìm kiếm: loại bỏ các số 0 đáng kể (tất nhiên chúng tôi đã thực hiện có ý nghĩa thông qua toFixedcuộc gọi). đó là một trường hợp cạnh UX kỳ lạ.
worc

12

Về cơ bản, tôi đã có cùng một yêu cầu và thấy rằng không có cơ chế tích hợp nào cho chức năng này.

Ngoài việc cắt bớt các số 0 ở cuối, tôi cũng có nhu cầu làm tròn và định dạng đầu ra cho miền địa phương hiện tại của người dùng (ví dụ 123,456.789).

Tất cả công việc của tôi về điều này đã được đưa vào dưới dạng beautifulFloat.js (Được cấp phép MIT) trên GitHub: https://github.com/dperish/prettyFloat.js


Ví dụ sử dụng:

prettyFloat(1.111001, 3) // "1.111"
prettyFloat(1.111001, 4) // "1.111"
prettyFloat(1.1111001, 5) // "1.1111"
prettyFloat(1234.5678, 2) // "1234.57"
prettyFloat(1234.5678, 2, true) // "1,234.57" (en-us)


Cập nhật - Tháng 8 năm 2018


Tất cả các trình duyệt hiện đại hiện hỗ trợ API quốc tế hóa ECMAScript , cung cấp so sánh chuỗi nhạy cảm ngôn ngữ, định dạng số và định dạng ngày và giờ.

let formatters = {
    default: new Intl.NumberFormat(),
    currency: new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 0, maximumFractionDigits: 0 }),
    whole: new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 0, maximumFractionDigits: 0 }),
    oneDecimal: new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 1, maximumFractionDigits: 1 }),
    twoDecimal: new Intl.NumberFormat('en-US', { style: 'decimal', minimumFractionDigits: 2, maximumFractionDigits: 2 })
};

formatters.twoDecimal.format(1234.5678);  // result: "1,234.57"
formatters.currency.format(28761232.291); // result: "$28,761,232"

Đối với các trình duyệt cũ hơn, bạn có thể sử dụng polyfill này: https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en


Đây là những gì đã tìm kiếm. Bạn phải tạo một gói npm.
EnZo

Vì vậy, tôi có lẽ nên cập nhật điều này, vì điều này hiện có thể thông qua API quốc tế hóa.
dperish

2
Điều này rất hữu ích, cảm ơn vì đã chia sẻ và cảm ơn vì đã cập nhật.
jaggedsoft

11

Làm thế nào về chỉ nhân với một như thế này?

var x = 1.234000*1; // becomes 1.234

var y = 1.234001*1; // stays as 1.234001

9

Bạn có thể thử cái này để giảm bớt số trôi nổi

var n = 0.0000;
n = parseFloat(n.toString()); 

//output n = 0; 
// n = 3.14000; --> n = 3.14;

7

Câu trả lời thuần túy

n.replace(/(\.[0-9]*[1-9])0+$|\.0*$/,'$1');

Tôi tự hỏi tại sao không ai cho!


Nó sẽ không hoạt động với các số (số được nêu trong câu hỏi ban đầu). Tôi yêu các giải pháp cho một đại diện chuỗi mặc dù!
BennyHilarious

6

Tôi cũng cần phải giải quyết vấn đề này khi Django hiển thị các giá trị loại thập phân trong trường văn bản. Ví dụ: khi '1' là giá trị. Nó sẽ hiển thị '1.00000000'. Nếu '1,23' là giá trị, nó sẽ hiển thị '1.23000000' (Trong trường hợp cài đặt 'binary_places' là 8)

Sử dụng parseFloat không phải là một lựa chọn cho tôi vì có thể nó không trả về cùng một giá trị. toFixed không phải là một tùy chọn vì tôi không muốn làm tròn bất cứ điều gì, vì vậy tôi đã tạo một hàm:

function removeTrailingZeros(value) {
    value = value.toString();

    # if not containing a dot, we do not need to do anything
    if (value.indexOf('.') === -1) {
        return value;
    }

    # as long as the last character is a 0 or a dot, remove it
    while((value.slice(-1) === '0' || value.slice(-1) === '.') && value.indexOf('.') !== -1) {
        value = value.substr(0, value.length - 1);
    }
    return value;
}

Điều này hoạt động, tuy nhiên nó khá kém hiệu quả, vì nó dẫn đến việc tạo ra nhiều chuỗi cho mỗi lần thực hiện. Hãy tưởng tượng chạy cái này trên tất cả các ô trong một bảng, trong đó một số tốt là 0,00000. Một lựa chọn tốt hơn sẽ là xác định có bao nhiêu số 0 ở đó, sau đó thực hiện lát cắt trong một lần. Xác định một ký tự là gì, phần lớn là hiệu quả, việc tách chuỗi ít hơn như vậy.
Derek Nigel Bartram

Tôi đã làm một cái gì đó tương tự như đề xuất của bạn Derek: github.com/rek/remove-trailing-zeros/blob/master/iêu
rekarnar

Thử nghiệm hoàn hảo có ở đây: jsperf.com/remove-trailing-zeros/1 , bạn đã đúng, việc tìm các số không và loại bỏ chúng là cách nhanh hơn!
rekarnar

4

Không có giải pháp nào trong số này làm việc cho tôi với số lượng rất nhỏ. http://numeraljs.com/ đã giải quyết điều này cho tôi.

parseFloat(0.00000001.toFixed(8));
// 1e-8

numeral(0.00000001).format('0[.][00000000]');
// "0.00000001"

Nó không thể xử lý hơn 6 độ chính xác. Tôi muốn nói rằng thư viện này là vô dụng nếu nó có nghĩa là cho số lượng nhỏ. Chắc chắn không nên.
Daniel Kmak

2

Nếu bạn không thể sử dụng Floats vì bất kỳ lý do nào (như tiền nổi có liên quan) và đã bắt đầu từ một chuỗi đại diện cho một số chính xác, bạn có thể thấy giải pháp này tiện dụng. Nó chuyển đổi một chuỗi đại diện cho một số thành một chuỗi đại diện cho số không theo dõi số 0.

function removeTrailingZeroes( strAmount ) {
    // remove all trailing zeroes in the decimal part
    var strDecSepCd = '.'; // decimal separator
    var iDSPosition = strAmount.indexOf( strDecSepCd ); // decimal separator positions
    if ( iDSPosition !== -1 ) {
        var strDecPart = strAmount.substr( iDSPosition ); // including the decimal separator

        var i = strDecPart.length - 1;
        for ( ; i >= 0 ; i-- ) {
            if ( strDecPart.charAt(i) !== '0') {
                break;
            }
        }

        if ( i=== 0 ) {
            return strAmount.substring(0, iDSPosition);
        } else {
            // return INTPART and DS + DECPART including the rightmost significant number
            return strAmount.substring(0, iDSPosition) + strDecPart.substring(0,i + 1);
        }
    }

    return strAmount;
}

0

Sau khi đọc tất cả các câu trả lời - và bình luận - tôi đã kết thúc với điều này:

function isFloat(n) {
    let number = (Number(n) === n && n % 1 !== 0) ? eval(parseFloat(n)) : n;
    return number;
}

Tôi biết sử dụng eval có thể có hại bằng cách nào đó nhưng điều này đã giúp tôi rất nhiều.

Vì thế:

isFloat(1.234000);     // = 1.234;
isFloat(1.234001);     // = 1.234001
isFloat(1.2340010000); // = 1.234001

Nếu bạn muốn giới hạn các vị trí thập phân, hãy sử dụng toFixed()như những người khác đã chỉ ra.

let number = (Number(n) === n && n % 1 !== 0) ? eval(parseFloat(n).toFixed(3)) : n;

Đó là nó.


0

Tôi cần phải xóa bất kỳ số 0 nào, nhưng giữ ít nhất 2 số thập phân, bao gồm mọi số không.
Các số tôi đang làm việc là 6 chuỗi số thập phân, được tạo bởi .toFixed (6).

Kết quả dự kiến:

var numstra = 12345.000010 // should return 12345.00001
var numstrb = 12345.100000 // should return 12345.10
var numstrc = 12345.000000 // should return 12345.00
var numstrd = 12345.123000 // should return 12345.123

Giải pháp:

var numstr = 12345.100000

while (numstr[numstr.length-1] === "0") {           
    numstr = numstr.slice(0, -1)
    if (numstr[numstr.length-1] !== "0") {break;}
    if (numstr[numstr.length-3] === ".") {break;}
}

console.log(numstr) // 12345.10

Hợp lý:

Chạy hàm vòng lặp nếu chuỗi ký tự cuối cùng bằng 0.
Xóa ký tự cuối cùng và cập nhật biến chuỗi.
Nếu chuỗi ký tự cuối cùng được cập nhật không phải là số 0, vòng lặp kết thúc.
Nếu chuỗi được cập nhật thứ ba đến ký tự cuối cùng là một dấu chấm động, vòng lặp kết thúc.


-1

Đây là một giải pháp khả thi:

var x = 1.234000 // to become 1.234;
var y = 1.234001; // stays 1.234001

eval(x) --> 1.234
eval(y) --> 1.234001

4
Bạn không cần eval cho nhiệm vụ đơn giản này! parseFloat()sẽ thích hợp hơn nhiều
hutchbat

6
eval == ác. Đừng sử dụng nó bao giờ
eagor

-2

Chỉ là một phép toán đơn giản để sử dụng toFixed

function truncateNumber( num, precision ){
    let c = Math.pow(10,precision);
    return Math.trunc( Math.round(num*c) )/c;
}
    
console.log( truncateNumber(1234.5678, 3) );
console.log( truncateNumber(1234.56, 3) );

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.