Hãy cẩn thận khi so sánh các số trong C++
C++ là ngôn ngữ lập trình được sử dụng rộng rãi, nhưng cũng là ngôn ngữ có lỗi lập trình phổ biến nhất. Nhiều lỗi trong số này là do lỗi logic. Cụ thể, các lỗi mắc phải trong quá trình so sánh có thể ảnh hưởng đến độ chính xác và độ tin cậy của mã của bạn.
Ngôn ngữ C++ có một lỗi so sánh cụ thể mà nhiều nhà phát triển mới bỏ qua. Lỗi này là do hiểu sai về cách thức hoạt động của toán tử khi thực hiện nhiều phép so sánh. Tìm hiểu làm thế nào để tránh sai lầm phổ biến này và tại sao nó lại xảy ra ngay từ đầu.
Mục Lục
So sánh trong C++
Ngôn ngữ lập trình C++ cung cấp nhiều tính năng và công cụ khác nhau, cùng với các thao tác cơ bản như toán tử so sánh. Toán tử so sánh là các phép toán đặc biệt trong ngôn ngữ lập trình mà bạn có thể sử dụng để so sánh dữ liệu với nhau. Các nhà phát triển sử dụng các toán tử này khá thường xuyên, đặc biệt là khi tạo các thuật toán.
Bạn có thể thấy các toán tử so sánh trong nhiều ví dụ khác nhau trong cuộc sống hàng ngày. Ví dụ: khi bạn mua sắm tại cửa hàng tạp hóa, bạn sẽ lưu ý đến các toán tử này để so sánh giá cả. Nếu giá sản phẩm này thấp hơn sản phẩm kia thì bạn chọn sản phẩm đó.
Bạn có thể thấy các toán tử so sánh trong câu lệnh if-else khá thường xuyên. Các toán tử so sánh là nơi để kiểm tra xem một giá trị có lớn hơn, nhỏ hơn hoặc bằng một giá trị khác hay không. Có một chi tiết rất nhỏ nhưng quan trọng mà bạn không nên bỏ qua. Kết quả của các biểu thức so sánh trả về true hoặc false, là các giá trị boolean. Các giá trị này là một trong những thành phần cơ bản của cấu trúc điều khiển trong lập trình.
Ví dụ, trong ngôn ngữ lập trình C++, dấu “==” Toán tử kiểm tra xem hai giá trị có bằng nhau không. Nếu các giá trị bằng nhau, kết quả trả về là true. Nếu không, kết quả sẽ là false.
if (a == b)
{
return true;
}
else
{
return false;
}
Một ví dụ về một vấn đề so sánh
Một trong những lỗi phổ biến mà những người mới bắt đầu học C++ mắc phải là sử dụng các toán tử so sánh. Các toán tử này cho phép lập trình viên so sánh hai giá trị và thực hiện các thao tác khác nhau dựa trên kết quả so sánh đó. Tuy nhiên, sử dụng sai các toán tử này có thể gây ra các lỗi không mong muốn.
Ví dụ, mặc dù biểu thức 3 < 15 < 10 là không chính xác về mặt toán học, C++ coi kết quả của nó là đúng. Bạn có thể chứng minh điều này bằng cách viết chương trình thử nghiệm đơn giản sau đây.
Đầu tiên, tạo một tệp có tên thử nghiệm.cpp. Mở tệp này bằng trình chỉnh sửa mã yêu thích của bạn và thêm đoạn mã sau vào tệp.
#include <iostream>
int a = 15;int main()
{
if (3 < a < 10)
{
std::cout << "foo" << std::endl;
}
else
{
std::cout << "boo" << std::endl;
}
return 0;
}
Bạn có thể sử dụng lệnh này để biên dịch và chạy mã:
g++ test.cpp -o Test
Bây giờ bạn có một chương trình gọi là Bài kiểm tra. Chạy chương trình và kiểm tra đầu ra của nó.
C++ coi 3 < 15 < 10 là đúng khi chạy chương trình này. Tại sao kết quả có thể xảy ra theo cách này, mặc dù đó là một phát biểu không chính xác về mặt toán học?
Nguyên nhân của vấn đề so sánh trong C++
Giống như hầu hết các ngôn ngữ lập trình, C++ đọc mã từ trái sang phải. Mỗi toán tử so sánh tạo ra một giá trị boolean. Giá trị Boolean không chỉ có nghĩa là đúng và sai; họ có một tương đương toán học.
Nguyên lý làm việc của máy tính phụ thuộc vào số 1 và số 0. Đối với máy tính, kết quả của một cái gì đó là đúng hoặc sai. Các chương trình máy tính thường coi số 1 là đúng và số 0 là sai.
Kiểm tra lại vấn đề so sánh và đọc câu lệnh từ trái sang phải; bạn sẽ thấy rằng có hai so sánh khác nhau. So sánh đầu tiên là giữa các số 3 và 15. Đây là một giá trị thực vì 3 nhỏ hơn 15.
So sánh thứ hai là giữa kết quả đó và số 10. Vì cần thực hiện so sánh số, C++ âm thầm chuyển đổi giá trị thực boolean thành 1. 1 nhỏ hơn 10, vì vậy kết quả chung là đúng.
Tóm lại, mặc dù có vẻ như là một sai lầm toán học, nhưng tuyên bố này đúng với C++ và máy tính.
Cách giải quyết vấn đề so sánh trong C++
C++, cùng với hầu hết các ngôn ngữ lập trình khác, sử dụng cú pháp so sánh logic khác với toán học truyền thống. Biểu thức toán học 3 < a < 15 có nghĩa là “3 nhỏ hơn a Và a nhỏ hơn 15.” Tuy nhiên, như bạn đã thấy, C++ diễn giải biểu thức đó theo cách khác.
Để biểu diễn và trong C++, hãy sử dụng toán tử &&. Sau đó, bạn có thể xâu chuỗi các biểu thức boolean lại với nhau và xây dựng logic bằng cách sử dụng các toán tử như && để đại diện cho VÀ, || để đại diện cho OR, và ! để đại diện cho KHÔNG. Các ngôn ngữ như Java sử dụng cùng một toán tử logic.
Sử dụng toán tử logic chính xác, bạn có thể sửa lỗi trong ví dụ trước:
#include <iostream>
int a = 15;int main()
{
if (3 < a && a < 10)
{
std::cout << "foo" << std::endl;
}
else
{
std::cout << "boo" << std::endl;
}
return 0;
}
Bây giờ đoạn mã này sẽ kiểm tra xem giá trị a có lớn hơn 3 và giá trị a có nhỏ hơn 10 hay không. Biên dịch và chạy chương trình và quan sát kết quả.
Ví dụ trước in ra “foo”, nhưng chương trình bây giờ in ra “boo” như dự kiến. Giá trị boolean của vế trái của phép so sánh (3 < a) là đúng. Giá trị của vế phải (a < 10) là sai. Từ đúng và sai luôn luôn là SAIbiểu thức tổng thể đánh giá là sai, do đó điều kiện đó không thành công và khác khối chạy.
Hãy thử chuyển AND (&&) thành toán tử OR (||) và quan sát kết quả khác nhau.
Tầm quan trọng của kiểm tra logic trong C++
So sánh logic trong C++ liên quan đến việc sử dụng các giá trị boolean và toán tử so sánh. Đảm bảo rằng bạn sử dụng đúng giá trị boolean và toán tử so sánh để kiểm soát hoạt động của chương trình. Có thể khó phát hiện ra các biểu thức được định dạng sai vì C++ thường sẽ thực hiện các hành vi khác thay vì thất bại hoàn toàn.
Bây giờ bạn đã biết trình biên dịch bỏ qua vấn đề này như thế nào và coi mỗi phép so sánh là một giá trị logic khi đọc từ trái sang phải. Hãy coi chừng vấn đề này trong bất kỳ ngôn ngữ nào bạn sử dụng và học cách nhận ra tác động của nó để bạn có thể đi trước một bước.