2017-02-10 17 views
5

Miễn là điểm nổi được sử dụng, 0,1 không thể được biểu diễn chính xác trong bộ nhớ, vì vậy chúng tôi biết rằng giá trị này thường xuất hiện ở mức 0.10000000000000004.Tại sao 0.1 + 0.2 nhận được 0.3 trong Google Go?

Nhưng khi sử dụng, hãy thêm 0,1 và 0,2. Tôi nhận được 0,3.

fmt.Println(0.1 + 0.2) 
// Output : 0.3 

Tại sao 0,3 ra ngoài thay vì 0,30000000000000004?

+0

Hãy chắc chắn rằng Go không liên tục lần biểu thức, vì Go sử dụng chính xác thêm tại thời gian biên dịch. – user2357112

+0

Nhờ có điều mới! – Integral

Trả lời

5

Đó là vì khi bạn in nó (ví dụ: với gói fmt), chức năng in đã tròn thành một số lượng chữ số thập phân nhất định.

Xem ví dụ này:

const ca, cb = 0.1, 0.2 
fmt.Println(ca + cb) 
fmt.Printf("%.20f\n", ca+cb) 

var a, b float64 = 0.1, 0.2 
fmt.Println(a + b) 
fmt.Printf("%.20f\n", a+b) 

Output (thử nó trên Go Playground):

0.3 
0.29999999999999998890 
0.30000000000000004 
0.30000000000000004441 

Đầu tiên chúng tôi sử dụng constants bởi vì đó là khác nhau so với sử dụng các giá trị (không liên tục) loại float64. Hằng số số đại diện cho các giá trị chính xác của độ chính xác tùy ý và không tràn.

Nhưng khi in kết quả của ca+cb, giá trị không đổi phải được chuyển đổi thành giá trị được nhập không đổi, không đổi để có thể được chuyển đến fmt.Println(). Giá trị này sẽ thuộc loại float64, không thể đại diện chính xác cho 0.3. Nhưng fmt.Println() sẽ làm tròn nó thành ~ 16 số thập phân, sẽ là 0.3. Nhưng khi chúng tôi tuyên bố rõ ràng chúng tôi muốn nó hiển thị với 20 chữ số, chúng tôi sẽ thấy nó không chính xác. Lưu ý rằng chỉ 0.3 mới được chuyển đổi thành float64, vì số học không đổi 0.1+0.2 sẽ được trình biên dịch đánh giá (tại thời gian biên dịch). Tiếp theo chúng ta bắt đầu với các biến kiểu float64, và không ngạc nhiên, đầu ra không phải là 0.3 chính xác, nhưng lần này ngay cả với làm tròn mặc định, chúng tôi nhận được kết quả khác với 0.3. Lý do cho điều này là vì trong trường hợp đầu tiên (hằng số) là 0.3 đã được chuyển đổi, nhưng lần này cả hai 0.10.2 được chuyển đổi thành float64, không ai trong số đó là chính xác và thêm chúng dẫn đến một số có khoảng cách lớn hơn từ 0.3 , đủ lớn để tạo "hình ảnh trực quan" với phần làm tròn mặc định của gói fmt.

Kiểm tra tương tự/câu hỏi có liên quan + câu trả lời cho biết thêm về chủ đề:

Why do these two float64s have different values?

How does Go perform arithmetic on constants?

Golang converting float64 to int error

Does go compiler's evaluation differ for constant expression and other expression

Why does adding 0.1 multiple times remain lossless?

Golang Round to Nearest 0.05

Go: Converting float64 to int with multiplier

+0

Cảm ơn bạn! xin lỗi tôi tới trễ. Nó đã giúp rất nhiều !! – Integral

Các vấn đề liên quan