Kiểu dữ liệu number trong Javascript

Kiểu dữ liệu number trong Javascript

Có hai kiểu dữ liệu liên quan đến number trong JavaScript là: number thông thường và bigInt.

  1. Number thông thường được lưu dưới dạng số thực dấu phẩy động theo chuẩn IEEE-754 với độ chính xác kép.
  2. BigInt là kiểu dữ liệu dùng để biểu diễn số nguyên với độ dài tùy ý. Số bigInt được sử dụng trong một số trường hợp cần biểu diễn số nguyên lớn. Vì số thông thường không thể lớn hơn 253 và nhỏ hơn -253.

Kiểu bigInt là kiểu số đặc biết nên mình sẽ tìm hiểu sau. Bài viết này chỉ tập trung vào number thông thường.

Cách khác để biểu diễn number trong JavaScript

Giả sử bạn cần biểu diễn số 1 tỷ:

let oneBillion = 1000000000;

Nếu bạn chỉ nhìn qua thì rất khó nhận biết đó là số 1 tỷ. Có thể bạn sẽ phải đếm xem có bao nhiêu số 0 trong đó.

Thay vì phải đếm như vậy, JavaScript cho phép bạn sử dụng kí tự gạch chân _ để phân tách các chữ số:

let oneBillion = 1_000 _000_000;

Rõ ràng cách viết này dễ nhìn hơn. Và kết quả thì vẫn không thay đổi. Vì JavaScript engine sẽ bỏ qua, không xử lý kí tự _ trong number.

Trong thực tế cuộc sống, chúng ta thường không muốn viết hết các chữ số 0 mà thường viết tắt, ví dụ: 1000 thành 1K, 1000000 thành 1M,…

Với JavaScript cũng vậy, bạn có thể dùng chữ cái e để biểu diễn số lượng chữ số 0, ví dụ:

let a = 1 e3;  
let b = 1 e6;  
let c = 1 e9;  
let d = 4.6 e9;  

Nói cách khác, eN thực hiện nhân số (trước e) bởi với số 10 mũ N.

1 e3 = = = 1 * 1000;  
1.23 e4 = = = 1.23 * 10000;  

Tương tự, bạn cũng có thể dùng e để biểu diễn những số rất nhỏ bằng cách thay N ở trên bằng số âm:

0.000001 = = = 1 e - 6;

Nói cách khác, e-N thực hiện chia số (trước e) bởi số 10 mũ N.

1 e - 3 = = = 1 / 1000;  
1.23 e - 4 = = = 1.23 / 10000;  

Biểu diễn số ở hệ cơ số 16, 8 và 2

Các số mình thường viết trên đây là màn biểu diễn ở hệ thập phân ( cơ số 10 ). Ngoài ra, bạn hoàn toàn có thể màn biểu diễn number trong JavaScript ở hệ thập lục phân ( cơ số 16 ), bát phân ( cơ số 8 ) và nhị phân ( cơ số 2 ) .

  • Hệ thập lục phân sử dụng tiền tố là 0x.
  • Hệ bát phân sử dụng tiền tố là 0o.
  • Hệ nhị phân sử dụng tiền tố là 0b.

màn biểu diễn số ở hệ 16, 8 và 2 là :

 
console.log(0 xff);  
console.log(0 xff);  

 
console.log(0 o377);  

 
console.log(0 b11111111);  

Phương thức num.toString(base) trả về string biểu diễn số num ở hệ cơ số base, ví dụ:

let num = 255;

 
console.log(num.toString(16));  

 
console.log(num.toString(2));  

Trong đó, base có giá trị nằm trong đoạn từ 2 đến 36. Mặc định, base10.

Một số trường hợp phổ cập :

  • base=16 hay dùng để biểu diễn mã màu hexa, string đã được encode,… với các chữ số từ 0..9 hoặc A-F (không phân biệt hoa thường).
  • base=2 thường dùng để debug các số sử dụng trong toán tử bitwise… với các chữ số là 0 hoặc 1.
  • base=36 là giá trị lớn nhất, thường được dùng để biểu diễn các số dài thành dạng ngắn gọn hơn, với các chữ số từ 0..9A..Z, ví dụ:
console.log((1234567890).toString(36));  

cách viết dùng hai dấu chấm .. như trên không phải lỗi chính tả. Nếu bạn muốn gọi phương thức của number, ví dụ toString(), bạn cần phải dùng hai dấu chấm

Nếu bạn dùng một dấu chấm thì sẽ có lỗi cú pháp:

console.log(1234567890 .toString(36));
     

Bởi vì, JavaScript hiểu rằng sau dấu . đầu tiên là phần thập phân của số thực. Mà đằng sau . lại là toString thì chắc chắn sai cú pháp.

Ngược lại, khi bạn viết hai dấu chấm .., JavaScript ngầm định phần thập phân là rỗng, rồi sau đó đến phương thức.

Nói cách khác, cách viết hai dấu chấm .. tương đương với cách viết sử dụng () như sau:

 
console.log((1234567890).toString(36));  

Để code rõ ràng và an toàn hơn, bạn nên sử dụng ()

Làm tròn number trong JavaScript

Một trong những phép toán hay sử dụng với number trong JavaScript nhất là làm tròn số. JavaScript có sẵn một số hàm giúp bạn làm tròn số như:

Math.floor:

Từ floor dịch ra là sàn nhà – suy ra hàm Math.floor dùng để làm tròn xuống. Ví dụ: 3.1 trở thành 3-1.1 trở thành -2.

Math.ceil:

Từ ceil dịch ra là trần nhà – suy ra hàm Math.ceil dùng để làm tròn lên. Ví dụ: 3.1 trở thành 4-1.1 trở thành -1.

Math.round:

Hàm này trả về số nguyên gần nhất (có thể làm tròn lên hoặc làm tròn xuống). Ví dụ: 3.1 trả về 3, 3.6 trở thành 4 và giá trị ở giữa 3.5 cũng trở thành 4.

Math.trunc (không hỗ trợ bởi trình duyệt IE):

Hàm này trả về số nguyên bằng cách xóa bỏ đi tất cả thành phần sau dấu phẩy. Ví dụ: 3.1 trở thành 3-1.1 trở thành -1.

Trên đây là những hàm giúp làm tròn thành số nguyên. Vậy làm sao để làm tròn thành số thực với chính xác n chữ số sau dấu phẩy.

làm sao để làm tròn số 1.2345 thành 1.23 (2 chữ số sau dấu phẩy)?

hai cách để giải quyết vấn đề trên.

  1. Phương pháp nhân-rồi-chia:

Ví dụ để làm tròn 2 chữ số sau dấu phẩy, bạn nhân số ban đầu với 100 (2 chữ số 0). Sau đó, bạn dùng Math.round để làm tròn kết quả về số nguyên gần nhất. Cuối cùng, bạn chia kết quả cho 100 sẽ thu được kết quả như mong muốn.

let a = 1.2345;

 
let b = a * 100;  

 
let c = Math.round(b);  

 
let d = c / 100;  

console.log(d);  
  1. Sử dụng phương thức toFixed(n):

Phương thức này sẽ làm tròn số và trả về string với chính xác n chữ số sau dấu phẩy.

let a = 1.2345;
let b = a.toFixed(2);
console.log(b);  

Trường hợp phần thập phân không đủ n chữ số thì phương thức toFixed(n) tự động thêm các chữ số 0 phía sau cho đủ n chữ số.

let a = 1.2345;
let b = a.toFixed(6);
console.log(b);  

Để chuyển đổi kiểu dữ liệu string về number, bạn có thể dùng hàm Number() hoặc toán tử một ngôi +, ví dụ:

let a = 1.2345;
let b = a.toFixed(2);  

let c = Number(b);
console.log(c, typeof c);  

Sai số với number trong JavaScript

Trong JavaScript, số thông thường được biểu diễn dưới dạng số thực dấu phẩy động theo chuẩn IEEE-754. Định dạng này sử dụng 64 bit để lưu trữ một số, trong đó:

  • 52 bit dùng để lưu trữ các chữ số phần nguyên.
  • 11 bit để lưu trữ phần thập phân.
  • 1 bit để lưu trữ dấu (0 – số dương và 1 – số âm).

Nếu một số quá lớn, vượt ngoài khả năng biểu diễn của 64 bit thì sẽ trở thành Infinity hoặc -Infinity:

console.log(1 e500);  
console.log(-1 e500);  

Đối với các số thực, một vấn đề thường xuyên xảy ra là sự sai số.

Một ví dụ tầm cỡ :

console.log(0.1 + 0.2 = = = 0.3);  

Kết quả là false vì thực tế 0.1 + 0.2 bằng số khác:

console.log(0.1 + 0.2);  

Hiểu đơn giản là: khi biểu diễn số thực dưới dạng nhị phân trong máy tính, không có cách nào để biểu diễn chính xác số 0.10.2. Dẫn đến kết quả bị sai số như trên.

Ví dụ mình sử dụng phương thức toFixed(20) để xem giá trị thực sự của các số thế nào:

console.log((0.1).toFixed(20));  
console.log((0.2).toFixed(20));  

Rõ ràng là chúng không thực sự bằng 0.10.2.

Để giải quyết vấn đề này, bạn có thể sử dụng phương pháp nhân-rồi-chia hoặc phương thức toFixed(1) như mình đã đề cập ở trên:

let a = 0.1;
let b = 0.2;

 
let sum1 = (a * 10 + b * 10) / 10;
console.log(sum1);  

 
let sum2 = (a + b).toFixed(1);
console.log(sum2);  

Kiểm tra số với isNaNisFinite

Để kiểm tra number trong JavaScript, bạn có thể dùng một trong hai hàm là: isNaN hoặc isFinite.

► HàmisNaN(value):

Hàm này chuyển đổi value thành dạng số rồi kiểm tra xem có bằng NaN hay không.

console.log(isNaN(NaN));  
console.log(isNaN(1));  
console.log(isNaN(" 1 "));  
console.log(isNaN(" abc "

)

);

Vấn đề là hàm isNaN có thật sự cần thiết hay không?

Câu trả lời là . Bởi vì giá trị NaN là duy nhất. NaN không bằng bất kỳ giá trị nào khác:

let a = NaN;
let b = NaN;

console.log(a = = = a);  
console.log(a = = = b);  

Nghĩa là bạn không thể dùng toán tử so sánh bằng === để so sánh số với NaN.

► Hàm isFinite(value):

Hàm này chuyển đổi giá trị value thành dạng số và trả về true nếu số đó khác Infinity, -InfinityNaN, ngược lại thì trả về false.

console.log(isFinite(" 1 "));  
console.log(isFinite(" abc "));  
console.log(isFinite(1 e500));  

Hàm isFinite(value) cũng thường dùng để kiểm tra một giá trị string có phải là số bình thường hay không.

Ví dụ khi nhập vào một số với hàm prompt:

let num = +prompt(" Nhập vào 1 số ít : ", " ");

 
 
console.log(isFinite(num));

String rỗng hoặc string toàn dấu cách chuyển sang dạng số thành số 0.

Để so sánh hai number trong JavaScript, bạn cũng có thể dùng phương thức Object.is:

  1. Phương thức này sử dụng được với NaN: Object.is(NaN,NaN) bằng true.
  2. Hai giá trị 0-0 là khác nhau: Object.is(0,-0) bằng false. Bởi vì JavaScript sử dụng 1 bit để biểu diễn dấu (0 – số dương và 1 – số âm), nên hai giá trị 0-0 khác nhau.

Trong hầu hết các trường hợp, phương thức Object.is tương đương với so sánh bằng nghiêm ngặt ===.

Hàm parseInt và hàm parseFloat

Có thể bạn đã biết hai cách để quy đổi string thành dạng số là :

  • Sử dụng hàm Number().
  • Sử dụng toán tử một ngôi +.
console.log(Number(" 1.23 "));  
console.log(+" 1.23 ");  

Tuy nhiên, nếu trong string chứa kí tự không phải dạng số thì kết quả là NaN:

console.log(Number(" 100 px "));  
console.log(+" 100 px ");  

Thực tế, có một số trường hợp string chứa cả số và đơn vị phía sau như 100px, 10rem, 1.1em,… Làm sao để tách lấy phần số từ các string này?

Trong JavaScript, bạn có thể sử dụng hai hàm parseIntparseFloat. Hai hàm này sẽ đọc string từ trái sang phải cho đến khi gặp kí tự không thỏa mãn thì dừng lại.

  • Hàm parseInt tách lấy số nguyên.
  • Hàm parseFloat tách lấy số thực.

Một số ví dụ :

console.log(parseInt(" 100 px "));  
console.log(parseFloat(" 1.1 em "));  

console.log(parseInt(" 1.2 "));  
console.log(parseFloat(" 1.2.3 "));  

Nếu không thể tách được số nào thì parseIntparseFloat trả về NaN:

console.log(parseInt(" USD 100 "));  
console.log(parseFloat(" USD 100 "));  

hàm parseInt(value, radix) có tham số thứ hai radix biểu diễn hệ cơ số (từ 2 đến 36)

Ví dụ tách lấy số nguyên ở những hệ cơ số khác nhau :

console.log(parseInt(" 0 xff ", 16));  
console.log(parseInt(" ff ", 16));  

console.log(parseInt(" kf12oi ", 36));  
console.log(parseInt(" 100 ", 2));  

Một số hàm toán học

Ngoài các phương thức Math.floor, Math.ceil, Math.roundMath.trunc đã trình bày ở trên, đối tượng Math còn có các phương thức khác giúp bạn thực hiện một số hàm toán học.

Math.random()

Phương thức này trả về một giá trị ngẫu nhiên từ 0 đến 1 (không bao gồm 1), ví dụ:

console.log(Math.random());  
console.log(Math.random());  
console.log(Math.random());  

Math.max(a, b, c,...)Math.min(a, b, c,...)

Hai phương pháp này trả về giá trị lớn nhất ( nhỏ nhất ) từ một dãy số nguồn vào .

console.log(Math.max(1, 3.2, -1, 10, 4));  
console.log(Math.min(1, 3.2, -1, 10, 4));  

Math.pow(n, base)

Trả về số nbase.

console.log(Math.pow(2, 3));  

Đối tượng Math còn rất nhiều phương thức hữu ích khác. Bạn có thể tham khảo thêm tại bài viết: Math.

Tổng kết

Sau đây là một số ít kỹ năng và kiến thức về number trong JavaScript .

Bạn có thể dùng kí tự _ để ngăn cách các chữ số cho dễ nhìn. Ví dụ 1_000_000_000 tương đương 1000000000.

Trường hợp có nhiều chữ số 0 đằng sau, bạn có thể dùng kí tự e theo sau là một số N để biểu diễn:

  • Với N dương thì eN tương đương nhân với 10 mũ N, ví dụ: 2e6 bằng 2000000.
  • Với N âm thì eN tương đương chia cho 10 mũ N, ví dụ: 2e-6 bằng 0.000002.

JavaScript tương hỗ màn biểu diễn số ở hệ cơ số khác :

  • Hệ cơ số 16 sử dụng tiền tồ 0x.
  • Hệ cơ số 8 sử dụng tiền tố 0o.
  • Hệ cơ số 2 sử dụng tiền tố 0b.

Để chuyển một số sang string với hệ cơ số tương ứng, bạn dùng num.toString(base), với base là hệ cơ số có giá trị từ 2 đến 36.

Để kiểm tra xem một số có phải NaN hay không, bạn dùng hàm isNaN. Hàm isNaN(value) chuyển giá trị value thành dạng số, rồi trả về true nếu số đó là NaN, ngược lại thì trả về false.

Để kiểm tra xem một số có phải số thông thường hay không, bạn dùng isFinite. Hàm isFinite(value) chuyển giá trị value thành dạng số, rồi trả về true nếu số đó khác Infinity, -InfinityNaN.

Để chuyển đổi string thành dạng số, bạn có thể dùng hàm parseInt hoặc hàm parseFloat. Cả hai hàm này đều đọc string từ trái sang phải cho đến khi gặp kí tự không thỏa mãn thì dừng lại:

  • Hàm parseInt: tách lấy phần số nguyên.
  • Hàm parseFloat: tách lấy phần số thực.

Đối tượng Math có các phương thức giúp bạn thực hiện các phép toán số học với number trong JavaScript như:

  • Làm tròn số: Math.floor, Math.ceil, Math.roundMath.trunc.
  • Tìm số ngẫu nhiên: Math.random.
  • Tìm giá trị lớn nhất / nhỏ nhất: Math.max, Math.min.
  • Tính lũy thừa: Math.pow.

Thực hành

Bài 1

Viết code thực thi nhu yếu sau :

  1. Dùng hàm prompt yêu cầu người dùng nhập vào hai số.
  2. Tính và hiển thị tổng hai số.

Xem đáp án

 
let a = +prompt(" Nhập vào số thứ nhất : ", 0);
let b = +prompt(" Nhập vào số thứ hai : ", 0);

 
console.log(a + b);

Bài 2

Viết hàm readNumber thực hiện yêu cầu sau:

  1. Dùng hàm prompt hỏi người dùng để nhập vào số.
  2. Nếu người dùng nhập vào số bình thường thì dừng lại và trả về số đó.
  3. Ngược lại, nếu người dùng không nhập vào số bình thường thì tiếp tục hỏi.

Xem đáp án

 
function readNumber() {
  while (true) {
     
    let n = prompt(" Nhập vào số : ", 0);

     
    if (n = = = " " | | n = = = null | | n = = = undefined | | !isFinite(n)) {
      continue;
    }

    return +n;
  }
}

 
let n = readNumber();
console.log

(

n);

Tham khảo :

  • Numbers
  • Số thực dấu phẩy động IEEE-7554