Làm thế nào để printf vòng một nửa đến vị trí thập phân đầu tiên?


11

Tôi đang thử nghiệm hai triển khai khác nhau printftrên hệ thống của mình: printf (GNU coreutils) 8.26và phiên bản đi kèm zsh 5.3.1. Tôi đang kiểm tra làm thế nào một nửa số được làm tròn, tức là cho 1,5, 2,5, 3,5, 9,5.

$ for i in {1..9}; do /usr/bin/printf '%.0f\n' "${i}.5"; done
2
2
4
4
6
6
8
8
10
$ for i in {1..9}; do printf '%.0f\n' "${i}.5"; done
2
2
4
4
6
6
8
8
10

Ở đây, cả hai rõ ràng tròn một nửa đến chẵn . Tuy nhiên, khi tôi kiểm tra làm tròn đến vị trí thập phân đầu tiên, mọi thứ trở nên khó hiểu. Đó là, tôi đang thử nghiệm cho 1.15, 1.25, 1.35, bản 1.95.

$ for i in {1..9}; do /usr/bin/printf '%.1f\n' "1.${i}5"; done
1.1
1.2
1.4
1.5
1.5
1.6
1.8
1.9
2.0
$ for i in {1..9}; do printf '%.1f\n' "1.${i}5"; done
1.1
1.2
1.4
1.4
1.6
1.6
1.8
1.9
1.9

Cả hai cách thực hiện đều khác nhau và tôi không thể thấy bất kỳ mô hình rõ ràng nào trong cả hai. Làm thế nào để hai printfnửa vòng tròn đến vị trí thập phân đầu tiên?

Câu trả lời:


19

GNU printf sử dụnglong double trong khi zsh sử dụng doubles thường xuyên . Hành vi làm tròn mà bạn thấy là bởi vì (giả sử) 1,45 không thể được biểu diễn dưới dạng tổng lũy ​​thừa của 2, đó là cách hoạt động của biểu diễn dấu phẩy động của IEEE 754 và độ gần đúng gần nhất thay đổi theo độ chính xác. Nó nhiều hơn một chút (với 80 bit) hoặc ít hơn (với 64 bit), do đó làm tròn lên hoặc xuống như bạn thấy.

Đã bao giờ, nếu bạn quan tâm đến biểu diễn và làm tròn chính xác ở cấp độ con người, đừng sử dụng dấu phẩy động.


1
Chỉ cần lưu ý rằng x.25 và x.75 (đối với x nhỏ phù hợp) có biểu diễn nhị phân chính xác, không giống như các biểu thức khác.
Toby Speight
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.