CodeGym /Khóa học Java /Frontend SELF VI /Làm việc với số thực

Làm việc với số thực

Frontend SELF VI
Mức độ , Bài học
Có sẵn

1.1 Làm tròn số thực

Số thực (phân số) trong tiếng Anh gọi là floating point number – số dấu phẩy động: ở Mỹ dùng dấu chấm để phân cách phần nguyên và phần thập phân của số. Do đó có tên gọi float.

Như chúng ta đã thảo luận, khi chuyển đổi một số thực (float) thành số nguyên (int), nó luôn làm tròn xuống đến số nguyên — phần thập phân của nó bị loại bỏ. Và dễ dàng hình dung một tình huống khi cần làm tròn số thực đến số nguyên gần nhất hoặc thậm chí lên. Làm gì đây?

Trong JavaScript có hàm tích hợp sẵn round() cho trường hợp như vậy. Nó được tạo ra trước khi thư viện Math hình thành, vì vậy không nằm trong thư viện đó. Các hàm làm tròn xuống và làm tròn lên lại nằm trong thư viện math.

Hàm Math.round()

Hàm Math.round() làm tròn số đến số nguyên gần nhất:

    
      Math.round(so_thuc)
    
  

Hàm này sẽ trả về số nguyên gần nhất với số thực được truyền vào.

Ví dụ:

Lệnh Kết quả
let x = Math.round(4.1); 4
let x = Math.round(4.5); 5
let x = Math.round(4.9); 5

Hàm Math.ceil()

Hàm Math.ceil() làm tròn số đến số nguyên lên:

Lệnh Kết quả
let x = Math.ceil(4.1); 5
let x = Math.ceil(4.5); 5
let x = Math.ceil(4.9); 5

Hàm Math.floor()

Hàm Math.floor() làm tròn số đến số nguyên xuống:

Lệnh Kết quả
let x = Math.floor(4.1); 4
let x = Math.floor(4.5); 4
let x = Math.floor(4.9); 4

Nếu bạn gặp khó khăn trong việc nhớ các lệnh này, một bài học tiếng Anh nhỏ sẽ giúp bạn:

  • math — toán học
  • round — làm tròn
  • ceiling — trần
  • floor — sàn

1.2 Cấu trúc của số dấu phẩy động

Kiểu number trong JavaScript có thể lưu trữ giá trị trong khoảng từ -1.7*10308 đến +1.7*10308. Khoảng giá trị khổng lồ này được giải thích bởi kiểu number được cấu trúc khác so với kiểu số nguyên. Mỗi biến kiểu number chứa hai số: số thứ nhất được gọi là mantissa, số thứ hai là exponent.

Giả sử chúng ta có số 123456789, và chúng ta lưu nó vào biến kiểu number. Khi đó số này sẽ được chuyển đổi thành 1.23456789*108, và bên trong kiểu number sẽ lưu trữ các số — 1.234567898. Phần được tô đỏ là phần "quan trọng của số" (mantissa), phần xanh là exponent.

Cách tiếp cận này cho phép lưu trữ cả số rất lớn và số rất nhỏ. Nhưng vì kích thước của số bị giới hạn trong 8 byte (64 bit) và một phần bit được sử dụng để lưu exponent (cũng như dấu của số và dấu của exponent), chiều dài tối đa của mantissa bị giới hạn ở 15 chữ số.

Đây là mô tả rất đơn giản về cấu trúc của số thực: bạn có thể tìm thấy một mô tả đầy đủ hơn ở đây.

1.3 Mất độ chính xác khi làm việc với số thực

Khi làm việc với số thực bạn luôn cần nhớ rằng số thực là không chính xác. Luôn có lỗi làm tròn, lỗi chuyển đổi từ hệ thập phân sang hệ nhị phân và cuối cùng, phổ biến nhất là mất độ chính xác khi cộng/trừ các số có khoảng cách quá lớn.

Điều cuối là tình huống không mong đợi nhất với người mới học lập trình.

Nếu từ số 109 trừ đi 1/109, chúng ta sẽ nhận lại 109.

Trừ các số có khoảng cách quá lớn Giải thích
1000000000.000000000
-      0.000000001
1000000000.000000000
Số thứ hai quá nhỏ, và phần quan trọng của nó bị bỏ qua (được tô xám). Tô đỏ là 15 chữ số quan trọng.

Chỉ có thể nói rằng, lập trình không phải là toán học.

1.4 Nguy hiểm khi so sánh số thực

Có một nguy hiểm khác đối với lập trình viên khi so sánh số thực. Bởi vì khi làm việc với các số này, có thể tích luỹ lỗi làm tròn, có tình huống khi các số thực đáng lẽ phải bằng nhau, nhưng chúng không bằng. Và ngược lại: số đáng lẽ không bằng, nhưng lại bằng.

Ví dụ:

Lệnh Giải thích
let a = 1000000000.0
let b = 0.000000001
let c = a – b
Trong biến a sẽ có giá trị 1000000000.0.
Trong biến c sẽ có giá trị 1000000000.0
(số trong biến b quá nhỏ).

Trong ví dụ trên ac đáng lẽ không bằng nhau, nhưng thực tế là chúng bằng nhau.

Hãy xem một ví dụ khác:

Lệnh Giải thích
let a = 1.00000000000000001
let b = 1.00000000000000002
Trong biến a sẽ có giá trị 1.0.
Trong biến b sẽ có giá trị 1.0.

Trên thực tế, việc so sánh số thực được thực hiện như sau:

Nếu hiệu số của chúng (theo trị tuyệt đối) nhỏ hơn một số rất nhỏ nào đó, chúng được coi là bằng nhau.

Ví dụ:

JavaScript
    
      let a = 0.00000000012;
      let b = 0.000000000011;

      if (Math.abs(a - b) < 0.00001) {
        console.log("bằng nhau");
      } else {
        console.log("không bằng nhau");
      }
    
  
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION