bash
Trong bash
đó, có lẽ là tốt như nó được. Điều đó sử dụng một vỏ dựng sẵn. Nếu bạn cần kết quả trong một biến, bạn có thể sử dụng thay thế lệnh hoặc bash
cụ thể (mặc dù hiện tại cũng được hỗ trợ bởi zsh
):
printf -v int %.0f "$float"
Bạn có thể làm:
float=1.23
int=${float%.*}
Nhưng điều đó sẽ loại bỏ phần phân số thay vì cung cấp cho bạn số nguyên gần nhất và điều đó sẽ không hoạt động đối với các giá trị $float
tương tự 1.2e9
hoặc .12
chẳng hạn.
Cũng lưu ý các hạn chế có thể do biểu diễn bên trong của phao:
$ printf '%.0f\n' 1e50
100000000000000007629769841091887003294964970946560
Bạn nhận được một số nguyên, nhưng rất có thể bạn sẽ không thể sử dụng số nguyên đó ở bất cứ đâu.
Ngoài ra, như được lưu ý bởi @BinaryZebra, trong một số printf
triển khai (bash, ksh93, yash, không phải GNU, zsh, dash), nó bị ảnh hưởng bởi miền địa phương (dấu tách thập phân có thể .
hoặc ,
).
Vì vậy, nếu số float của bạn luôn được biểu thị bằng dấu phân cách thập phân và bạn muốn nó được xử lý như vậy bằng cách printf
bất kể ngôn ngữ của người dùng gọi tập lệnh của bạn, bạn cần sửa ngôn ngữ thành C:
LC_ALL=C printf '%.0f' "$float"
Với yash
, bạn cũng có thể làm:
printf '%.0f' "$(($float))"
(xem bên dưới).
MỘT BỘ MÔ TẢ CHÍNH THỨC CUNG CẤP MỘT TIÊU CHUẨN CHO THIẾT KẾ HỆ ĐIỀU HÀNH, ĐẶC BIỆT LÀ CÁC MÔ TẢ TƯƠNG THÍCH VỚI UNIX
printf "%.0f\n" 1.1
không phải là POSIX vì %f
không bắt buộc phải được POSIX hỗ trợ.
POSIXly, bạn có thể làm:
f2i() {
awk 'BEGIN{for (i=1; i<ARGC;i++)
printf "%.0f\n", ARGV[i]}' "$@"
}
Cái đó không bị ảnh hưởng bởi miền địa phương (dấu phẩy không thể là dấu phân cách thập phân awk
vì nó đã là một ký tự đặc biệt trong cú pháp ở đó ( print 1,2
giống như print 1, 2
để truyền hai đối số cho print
)
zsh
Trong zsh
(hỗ trợ số học dấu phẩy động (dấu tách thập phân luôn luôn là dấu chấm)), bạn có rint()
hàm toán học để cung cấp cho bạn số nguyên gần nhất dưới dạng float (như in C
) và int()
cung cấp cho bạn một số nguyên từ float (như in awk
). Vì vậy, bạn có thể làm:
$ zmodload zsh/mathfunc
$ i=$((int(rint(1.234e2))))
$ echo $i
123
Hoặc là:
$ integer i=$((rint(5.678e2)))
$ echo $i
568
Tuy nhiên lưu ý rằng trong khi double
s có thể đại diện cho số lượng rất lớn, số nguyên bị giới hạn hơn nhiều.
$ printf '%.0f\n' 1e123
999999999999999977709969731404129670057984297594921577392083322662491290889839886077866558841507631684757522070951350501376
$ echo $((int(1e123)))
-9223372036854775808
ksh93
ksh93 là lớp vỏ giống như Bourne đầu tiên hỗ trợ số học dấu phẩy động. ksh93 tối ưu hóa thay thế lệnh bằng cách không sử dụng đường ống hoặc rèn khi các lệnh chỉ là các lệnh dựng sẵn. Vì thế
i=$(printf '%.0f' "$f")
không ngã ba. Hoặc thậm chí tốt hơn:
i=${ printf '%.0f' "$f"; }
điều này cũng không làm ngã ba nhưng cũng không gặp phải rắc rối nào khi tạo môi trường subshell giả.
Bạn cũng có thể làm:
i=$((rint(f)))
Nhưng hãy cẩn thận với:
$ echo "$((rint(1e18)))"
1000000000000000000
$ echo "$((rint(1e19)))"
1e+19
Bạn cũng có thể làm:
integer i=$((rint(f)))
Nhưng thích cho zsh
:
$ integer i=1e18
$ echo "$i"
1000000000000000000
$ integer i=1e19
$ echo "$i"
-9223372036854775808
Coi chừng ksh93
số học dấu phẩy động tôn vinh cài đặt dấu phân cách thập phân ở miền địa phương (mặc dù đó ,
là toán tử toán học ( $((1,2))
sẽ là 6/5 ở miền địa phương Pháp / Đức ... và tương tự $((1, 2))
, đó là 2 trong một ngôn ngữ tiếng Anh) .
yash
yash cũng hỗ trợ số học dấu phẩy động nhưng không có các hàm toán học như ksh93
/ zsh
's rint()
. Bạn có thể chuyển đổi một số thành số nguyên mặc dù bằng cách sử dụng nhị phân hoặc toán tử (cũng hoạt động zsh
nhưng không hoạt động ksh93
). Tuy nhiên, xin lưu ý rằng nó cắt bớt phần thập phân, nó không cung cấp cho bạn số nguyên gần nhất:
$ echo "$((0.237e2 | 0))"
23
$ echo "$((1e19))"
-9223372036854775808
yash
tôn vinh dấu phân cách thập phân của miền địa phương trên đầu ra, nhưng không cho các hằng số nghĩa đen của dấu phẩy động trong các biểu thức số học của nó, điều này có thể gây ra sự ngạc nhiên:
$ LC_ALL=fr_FR.UTF-8 ./yash -c 'a=$((1e-2)); echo $(($a + 1))'
./yash: arithmetic: `,' is not a valid number or operator
Theo cách tốt, bạn có thể sử dụng các hằng số dấu phẩy động trong các tập lệnh sử dụng dấu chấm và không phải lo lắng rằng nó sẽ ngừng hoạt động ở các địa phương khác, nhưng vẫn có thể xử lý các số được người dùng thể hiện miễn là như bạn nhớ làm:
var=$((10.3)) # and not var=10.3
... "$((a + 0.1))" # and not "$(($a + 0.1))".
printf '%.0f\n' "$((10.3))" # and not printf '%.0f\n' 10.3