Kiểu số

JavaScript chỉ có kiểu số thực dấu chấm động

Không như các ngôn ngữ khác, JavaScript không có kiểu nguyên thông thường (ngoài kiểu bigint – số nguyên lớn). Bạn có thể biểu diễn cả số nguyên lẫn số thực bởi một kiểu số duy nhất:

98
123.45

Số nguyên thực ra vẫn là số thực nhưng không có phần thập phân, so sánh sau trả về kết quả đúng:

> 98 === 98.0
true

Cách viết số (literal số)

Cách viết các số nguyên

Ta có thể viết số nguyên trong nhiều hệ cơ số khác nhau:

// Hệ nhị phân (cơ số 2)
assert.equal(0b11, 3);

// Hệ bát phân (cơ số 8)
assert.equal(0o10, 8);

// Hệ thập phân (cơ số 10)
assert.equal(35, 35);

// Hệ thập lục phân (cơ số 16)
assert.equal(0xe7, 231);

Cách viết các số thực

Số thực, không như số nguyên chỉ được biểu diễn trong hệ thập phân.

Có thể viết số thực như viết các số lẻ thông thường:

> 35.0
35

Hoặc viết với phần mũ là eN nghĩa là “nhân với 10 mũ N”:

> 3e2
300
> 3e-2
0.03
> 0.3e2
30

Các toán tử số học

Các toán tử hai ngôi

Toán tửTênVí dụ
n + mCộng3 + 4 -> 7
n - mTrừ9 - 1 -> 8
n * mNhân3 * 2.25 -> 6.75
n / mChia5.625 / 5 -> 1.125
n % mChia lấy dư8 % 5 -> 3
-8 % 5 -> -3
n ** mn mũ m4 ** 2 -> 16

Các toán tử một ngôi

Toán tử cộng và trừ một ngôi

Toán tửTênVí dụ
+nCộng một ngôi+(-7) -> -7
-nTrừ một ngôi-(-7) -> 7

Cả hai đều ép kiểu toán hạng thành số:

> +'5'
5
> +'-12'
-12
> -'9'
-9

Toán tử tăng/giảm một

Toán tử tăng một ++ tăng giá trị toán hạng của nó thêm 1. Toán tử giảm một -- giảm giá trị toán hạng của nó đi 1.

Toán tử tăng một ++ và giảm một -- tồn tại ở hai dạng:

  • Toán hạng đặt trước toán tử.
  • Toán hạng đặt sau toán tử.

Sự khác biệt của hai dạng là ở giá trị trả về:

  • Toán hạng đặt trước: trả về giá trị của toán hạng trước khi bị tăng/giảm.
  • Toán hạng đặt sau: trả về giá trị của toán hạng sau khi bị tăng/giảm.

Ví dụ ở dạng toán hạng đặt trước toán tử:

let foo = 3;
assert.equal(foo++, 3);
assert.equal(foo, 4);

let bar = 3;
assert.equal(bar--, 3);
assert.equal(bar, 2);

Ví dụ ở dạng toán hạng đặt sau toán tử:

let foo = 3;
assert.equal(++foo, 4);
assert.equal(foo, 4);

let bar = 3;
assert.equal(--bar, 2);
assert.equal(bar, 2);

Chuyển đổi thành số

Có hai cách để chuyển một giá trị thành số:

  • Number(value)
  • +value (dùng toán tử cộng một ngôi)

Bảng sau cho biết kết quả của sự chuyển đổi:

xNumber(x)
undefinedNaN
null0
giá trị lôgicfalse -> 0, true -> 1
sốx (không thay đổi)
chuỗi'' -> 0
chuỗi dạng số -> xóa khoảng trắng hai đầu -> số mà chuỗi biểu diễn
chuỗi không có dạng số -> NaN
đối tượngcó thể tùy chỉnh được (qua phương thức .valueOf)

Các ví dụ:

assert.equal(Number(123.45), 123.45);

assert.equal(Number(''), 0);
assert.equal(Number('\n 123.45 \t'), 123.45);
assert.equal(Number('xyz'), NaN);

Có thể tùy chỉnh chuyển đối tượng thành số qua phương thức .valueOf. Để thay đổi viết lại phương thức .valueOf:

> Number({ valueOf() { return 123 } });
123

Các giá trị lỗi

Có hai giá trị số được trả về khi có lỗi:

  • NaN
  • Infinity

Giá trị NaN

NaN là viết tắt của “not a number” (không phải số). Trớ trêu là JavaScript xem nó là số:

> typeof NaN
'number'

Khi nào NaN xuất hiện?

NaN xuất hiện khi không thể phân tích một giá trị nào đó thành số:

> Number('$$$')
NaN
> Number(undefined)
NaN

NaN xuất hiện nếu một toán tử không thể thực hiện công việc của nó (thực hiện phép toán vô nghĩa):

> Math.log(-1)
NaN
> Math.sqrt(-1)
NaN

NaN được trả về nếu có một toán hạng hoặc đối số là NaN:

> NaN - 3
NaN
> 7 ** NaN
NaN

Kiểm tra NaN

NaN là giá trị duy nhất không bằng với mọi giá trị, kể cả chính nó:

const n = NaN;
assert.equal(n === n, false);

Có vài cách kiểm tra giá trị xNaN hay không:

const x = NaN;

assert.equal(Number.isNaN(x), true); // nên dùng
assert.equal(Object.is(x, NaN), true);
assert.equal(x !== x, true);

Tìm NaN trong mảng

Một số phương thức không thể tìm thấy giá trị NaN trong mảng:

> [NaN].indexOf(NaN)
-1

Một số có thể:

> [NaN].includes(NaN)
true
> [NaN].findIndex(x => Number.isNaN(x))
0
> [NaN].find(x => Number.isNaN(x))
NaN

Giá trị Infinity

Khi nào Infinity xuất hiện?

Infinity (vô cùng) xuất hiện nếu số vượt quá khả năng biểu diễn của JavaScript:

> Math.pow(2, 1023)
8.98846567431158e+307
> Math.pow(2, 1024)
Infinity

Infinity cũng xuất hiện khi chia một số cho không:

> 5 / 0
Infinity
> -5 / 0
-Infinity

Dùng Infinity làm giá trị mặc định

Infinity lớn hơn mọi số (ngoại trừ NaN) nên nó có thể dùng làm giá trị mặc định trong hàm tìm số nhỏ nhất:

function findMinium(numbers) {
  let min = Infinity;
  for (const n of numbers) {
    if (n < min) min = n;
  }
  return min;
}

assert.equal(findMinimum([5, -1, 2]), -1);
assert.equal(findMinimum([]), Infinity);

-Infinity nhỏ hơn mọi số (ngoại trừ NaN) nên có thể dùng làm giá trị mặc định trong hàm tìm số lớn nhất:

function findMaximum(numbers) {
  let max = -Infinity;
  for (const n of numbers) {
    if (n > max) max = n;
  }
  return max;
}

assert.equal(findMaximum([5, -1, 2]), 5);
assert.equal(findMaximum([]), Infinity);

Kiểm tra Infinity

Có hai cách thông dụng để kiểm tra x có là Infinity không.

const x = Infinity;

assert.equal(x === Infinity, true);
assert.equal(Number.isFinite(x), false);

Số nguyên trong JavaScript

JavaScript không có kiểu nguyên. Thay vì vậy, chúng được biểu diễn bởi số thực không có phần thập phân:

> 1 === 1.0
true
> Number.isInteger(1.0)
true

Chuyển đổi thành số nguyên

Cách được khuyên dùng là sử dụng một trong các phương thức sau của đối tượng Math:

  • Math.floor(n): trả về số nguyên lớn nhất nhỏ hơn hoặc bằng n
> Math.floor(2.1)
2
> Math.floor(2.9)
2
  • Math.ceil(n): trả về số nguyên nhỏ nhất lớn hơn hoặc bằng n
> Math.ceil(2.1)
3
> Math.ceil(2.9)
3
  • Math.round(n): trả về số nguyên “gần” n nhất với _.5 được làm tròn lên, ví dụ:
> Math.round(2.4)
2
> Math.round(2.5)
3
  • Math.trunc(n): xóa bỏ phần thập phân của n (phần sau dấu chấm):
> Math.trunc(2.1)
2
> Math.trunc(2.9)
2

Tham khảo nhanh

Các hàm toàn cục dùng cho số

JavaScript có các hàm toàn cục sau dùng cho các số:

  • isFinite(): trả về true nếu số hữu hạn (không phải InfinityNaN)
  • isNaN(): trả về true nếu số là NaN
  • parseFloat(): phân tích một chuỗi thành số thực
  • parseInt(): phân tích một chuỗi thành số nguyên

Các thuộc tính tĩnh của Number

  • .MAX_SAFE_INTEGER: số nguyên lớn nhất mà JavaScript biểu diễn được.
  • .MAX_VALUE: số thực dương lớn nhất JavaScript biểu diễn được.
  • .MIN_SAFE_INTEGER: sô nguyên nhỏ nhất JavaScript biểu diễn được.
  • .MIN_VALUE: số dương nhỏ nhất JavaScript biểu diễn được.
  • .NaN: giống như NaN

Các phương thức tĩnh của Number

  • .isFinite(): tương tự như hàm toàn cục isFinite.
  • .isInteger(): trả về true nếu là số nguyên:
> Number.isInteger(-17)
true
> Number.isInteger(33)
true
> Number.isInteger(33.1)
false
> Number.isInteger('33')
false
> Number.isInteger(NaN)
false
> Number.isInteger(Infinity)
false
  • .isNaN(): tương tự như hàm toàn cục isNaN()
  • .parseFloat(): tương tự như hàm toàn cục parseFloat()
  • .parseInt(): tương tự như hàm toàn cục parseInt()

Các phương thức của Number.prototype

  • .toExponential()
> 1234..toExponential() // 3 fraction digits
'1.234e+3'
> 1234..toExponential(5)
'1.23400e+3'
> 1234..toExponential(1)
'1.2e+3'
  • .toFixed()
> 0.00000012.toFixed(10) // no exponent
'0.0000001200'
> 0.00000012.toFixed()
'0'
  • .toPrecision()
> 1234..toPrecision(3)  // requires exponential notation
'1.23e+3'

> 1234..toPrecision(4)
'1234'

> 1234..toPrecision(5)
'1234.0'

> 1.234.toPrecision(3)
'1.23'
  • .toString()
> 4..toString(2) // binary (base 2)
'100'
> 4.5.toString(2)
'100.1'

> 255..toString(16) // hexadecimal (base 16)
'ff'
> 255.66796875.toString(16)
'ff.ab'

> 1234567890..toString(36)
'kf12oi'