C++ – Rounding errors with double type

Hôm nay trong CLB có một câu đố vui cuối tuần, vì được nhiều bạn quan tâm nên mình viết lại để chia sẻ cùng mọi người 🙂

Bạn hãy cho biết output và giải thích kết quả của đoạn code đưới đây (có thể dùng online C++ compiler tại đây)

#include <iostream>

using namespace std;
 
int main() {
 
    double n = 0.1 + 0.1 + 0.1;
   
    if (n == 0.3)
        cout << "GameUIT" << endl;
    else
        cout << "Danh Pham dep trai" <<endl;
               
    return 0;
}

Nếu bạn biết output và giải thích tại sao thì bạn không cần đọc bài này 😀

Số thực trong C++

Số thực trong C++ là kiểu số thực dấu chấm động, keyword để search trên Google là floating point numbers. Có hai type là floatdouble.

Một biến kiểu floating point là một cách biểu diễn xấp xỉ cho một số thực bằng cách đánh đổi độ chính xác (precision).

Nếu đã học qua môn Kiến trúc máy tính (IT006) thì bạn sẽ dễ hiểu tại sao. Quy chuẩn được quy định theo IEEE 754

Đối với các bạn sinh viên năm nhất, có thể hiểu đơn giản như sau:
– Máy tính lưu số theo hệ nhị phân.
– Các giá trị phân số thập phân (hệ 10) bằng các phân số nhị phân (các phân số có tử là 1, mẫu là lũy thừa của 2). Ví dụ: 0.125 = 1/8

Tuy nhiên, hầu hết các phân số hệ thập phân không có biểu diễn ở hệ nhị phân. Ví dụ: 0.1

Lúc đó thì sẽ dẫn đến việc phải chấp nhận sai số, bạn có thể xem tại đây để biết các số thực được biểu diễn như thế nào trong máy tính: link

mặc dù việc làm tròn này là không đáng kể – nhưng khi dồn lại nhiều sẽ dẫn đến một sai số lớn. Điều này khiến các ứng dụng liên quan đến tài chính, thanh toán hạn chế và hầu như không dùng kiểu float.

Cách khắc phục trong C++

Để so sánh hai số này thì thay vì dùng ==, ta sẽ viết một hàm để so sánh. Ví dụ:

#include <iostream>
#include <limits>
 
using namespace std;
 
bool compareFunc(double a, double b)
{
    return (a-b) <= numeric_limits<double>().epsilon() && (a-b) >= -numeric_limits<double>().epsilon();
}
 
int main(){
 
    double n = 0.1 + 0.1 + 0.1;
   
    if (compareFunc(n, 0.3))
        cout << "GameUIT" << endl;
    else
        cout << "Danh Pham dep trai" <<endl;
   
    return 0;
}

Tham khảo

cplusplus.com
learncpp.com

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a website or blog at WordPress.com

Up ↑

%d bloggers like this: