Làm tròn số dấu phẩy động
"Làm tròn số dấu phẩy động" nghĩa là gì?
Điều đó thật dễ dàng, rõ ràng ... Cuốn sách toán học của tôi ở đâu ...
Không, chúng tôi đã biết không có gì liên quan đến số dấu phẩy động là dễ dàng:
Để bắt đầu, có nhiều chế độ làm tròn:
Làm tròn lên?
Làm tròn xuống?
Làm tròn đến không?
Làm tròn đến gần nhất - quan hệ để thậm chí?
Làm tròn đến gần nhất - quan hệ từ số không?
Làm thế nào để xử lý các trường hợp góc? Làm thế nào để tìm ra những trường hợp góc?
OK, có vẻ như chúng tôi sử dụng tốt hơn việc triển khai tiêu chuẩn IEEE 754 và để hệ thống của chúng tôi xử lý vấn đề đó.
Để làm tròn số dấu phẩy động trong vỏ, dựa trên số học dấu phẩy động tiêu chuẩn, chúng ta cần ba bước:
- Chuyển đổi văn bản đầu vào từ một đối số dòng lệnh thành một số dấu phẩy động tiêu chuẩn.
- Làm tròn số dấu phẩy động bằng cách sử dụng triển khai IEEE 754 bình thường.
- Định dạng số dưới dạng một chuỗi cho đầu ra.
Hóa ra lệnh shell printf
có thể làm tất cả những điều này. Nó có thể được sử dụng để in số theo một đặc điểm kỹ thuật định dạng như được mô tả trong man 3 printf
. Các số được làm tròn hoàn toàn theo cách tiêu chuẩn nếu được yêu cầu cho định dạng đầu ra:
Lệnh
Làm tròn x
đến p
chữ số chính xác với đầu vào là đối số dòng lệnh:
printf "%.*f\n" "$p" "$x"
Hoặc trong một đường ống vỏ, với đầu vào của đầu x
vào tiêu chuẩn và p
làm đối số:
echo "$x" | xargs printf "%.*f\n" "$p"
Ví dụ:
$ printf '%.*f\n' 0 6.66
7
$ printf '%.*f\n' 1 6.66
6.7
$ printf '%.*f\n' 2 6.66
6.66
$ printf '%.*f\n' 3 6.66
6.660
$ printf '%.*f\n' 3 6.666
6.666
$ printf '%.*f\n' 3 6.6666
6.667
Bẫy xấu
Hãy coi chừng miền địa phương! Nó chỉ định dấu phân cách giữa phần tích phân và phần - .
như bạn có thể mong đợi.
Nhưng hãy xem chính bạn những gì xảy ra ở một địa phương của Đức, ví dụ:
$ LC_ALL=de_DE.UTF-8 printf '%.*f\n' 3 6.6666
6,667
Vâng, điều đó đúng 6,667
- sáu dấu phẩy sáu sáu bảy. Điều đó sẽ gây rối cho kịch bản của bạn chắc chắn.
(Nhưng chỉ dành cho hai khách hàng ở Đức. Ngoại trừ máy của nhà phát triển hiện đang gỡ lỗi cho những khách hàng này.)
Mạnh mẽ hơn
Để làm cho nó mạnh mẽ hơn, sử dụng:
LC_ALL=C /usr/bin/printf "%.*f\n" "$p" "$x"
hoặc là
echo "$x" | LC_ALL=C xargs /usr/bin/printf "%.*f\n" "$p"
Điều này cũng sử dụng /usr/bin/printf
thay vì vỏ dựng sẵn bash
hoặc zsh
để khắc phục những mâu thuẫn nhỏ trong việc thực hiện các printf
biến thể, và ngăn chặn hiệu ứng rất bẩn khi, tại một địa điểm của Đức, LC_ALL
được đặt, nhưng không được xuất. Sau đó, nội dung được sử dụng ,
và /usr/bin/printf
sử dụng .
...
Xem thêm %g
để làm tròn đến một số chữ số có nghĩa.
awk
.