이것은 bash에서 부동 소수점을 정수로 변환하는 올바른 방법입니까? 다른 방법이 있습니까?
flotToint() {
printf "%.0f\n" "$@"
}
%.0f
반올림 또는 내림됩니다. 너가 원하는게 그거야? printf "%d\n" "$@" 2>/dev/null
분수를자를 때 사용할 수 있습니다 .
이것은 bash에서 부동 소수점을 정수로 변환하는 올바른 방법입니까? 다른 방법이 있습니까?
flotToint() {
printf "%.0f\n" "$@"
}
%.0f
반올림 또는 내림됩니다. 너가 원하는게 그거야? printf "%d\n" "$@" 2>/dev/null
분수를자를 때 사용할 수 있습니다 .
답변:
에서 bash
, 아마 그것이 얻는만큼 좋을 것입니다. 그것은 쉘 내장을 사용합니다. 변수에 결과가 필요한 경우 명령 대체 또는 bash
특정을 사용할 수 있습니다 (이제도 지원합니다 zsh
).
printf -v int %.0f "$float"
당신은 할 수 있습니다 :
float=1.23
int=${float%.*}
그러나 가장 가까운 정수를 제공하는 대신 분수 부분을 제거하면 $float
like 1.2e9
또는 예 .12
를 들어 값이 작동하지 않습니다 .
또한 float의 내부 표현으로 인한 가능한 제한 사항에 유의하십시오.
$ printf '%.0f\n' 1e50
100000000000000007629769841091887003294964970946560
정수를 얻지 만 그 정수를 어디서나 사용할 수는 없습니다.
또한 @BinaryZebra가 지적한 것처럼 여러 printf
구현 (Bash, ksh93, yash, GNU가 아닌 zsh, dash)에서 로케일 ( .
또는 소수 자릿수 구분 기호)의 영향을받습니다 ,
.
따라서 부동 소수점이 항상 마침표로 소수 구분 기호로 표시되고 printf
스크립트를 호출하는 사용자의 로캘 에 관계없이 그대로 처리 하려면 로캘을 C로 수정해야합니다.
LC_ALL=C printf '%.0f' "$float"
로에게 yash
, 당신은 또한 할 수 있습니다 :
printf '%.0f' "$(($float))"
(아래 참조).
printf "%.0f\n" 1.1
POSIX %f
가 지원하지 않아도되므로 POSIX 가 아닙니다.
POSIXly, 당신은 할 수 있습니다 :
f2i() {
awk 'BEGIN{for (i=1; i<ARGC;i++)
printf "%.0f\n", ARGV[i]}' "$@"
}
하나는 로케일의 영향을받지 않습니다 (쉼표는 awk
이미 구문의 특수 문자 print 1,2
이므로 print 1, 2
두 개의 인수를 전달하는 것과 동일하므로 소수 구분 기호는 사용할 수 없습니다 print
)
에서 zsh
(소수점이 항상 기간) 인 부동 소수점 연산 지원 (), 당신은이 rint()
float로 (처럼 당신에게 가장 가까운 정수를주는 연산 기능 C
) 및 int()
(처럼 부동 소수점에서 당신에게 정수를 줄을 awk
). 그래서 당신은 할 수 있습니다 :
$ zmodload zsh/mathfunc
$ i=$((int(rint(1.234e2))))
$ echo $i
123
또는:
$ integer i=$((rint(5.678e2)))
$ echo $i
568
그러나 double
s는 매우 큰 수를 나타낼 수 있지만 정수는 훨씬 더 제한적입니다.
$ printf '%.0f\n' 1e123
999999999999999977709969731404129670057984297594921577392083322662491290889839886077866558841507631684757522070951350501376
$ echo $((int(1e123)))
-9223372036854775808
ksh93은 부동 소수점 산술을 지원하는 최초의 Bourne 유사 쉘입니다. ksh93은 명령이 내장 명령 일 때 파이프를 사용하지 않거나 포크를 사용하여 명령 대체를 최적화합니다. 그래서
i=$(printf '%.0f' "$f")
포크하지 않습니다. 또는 더 나은 :
i=${ printf '%.0f' "$f"; }
포크하지는 않지만 가짜 서브 쉘 환경을 만드는 데 어려움을 겪지 않습니다.
당신은 또한 할 수 있습니다 :
i=$((rint(f)))
그러나 다음을주의하십시오.
$ echo "$((rint(1e18)))"
1000000000000000000
$ echo "$((rint(1e19)))"
1e+19
당신은 또한 할 수 있습니다 :
integer i=$((rint(f)))
그러나 좋아하는 것 zsh
:
$ integer i=1e18
$ echo "$i"
1000000000000000000
$ integer i=1e19
$ echo "$i"
-9223372036854775808
조심하십시오 ksh93
하더라도 (로케일에서 소수점 산술 명예에게 소수 구분 설정을 부동 ,
(수학 연산자는 달리입니다 $((1,2))
로케일 ... 프랑스어 / 독일어 6/5이 될 것이며, 같은 $((1, 2))
) 영어 로케일에서 2입니다, .
YASH 또한 부동 소수점 연산을 지원하지만 같은 수학 함수가 없습니다 ksh93
/ zsh
'들 rint()
. 예를 들어 바이너리 또는 연산자를 사용하여 숫자를 정수로 변환 할 수 있습니다 (작동 zsh
하지만 작동 하지 않음 ksh93
). 그러나 소수점 이하 자릿수를 자르므로 가장 가까운 정수는 제공하지 않습니다.
$ echo "$((0.237e2 | 0))"
23
$ echo "$((1e19))"
-9223372036854775808
yash
출력에서 로케일의 소수점 구분 기호를 사용하지만 산술 표현식의 부동 소수점 리터럴 상수에는 적용되지 않습니다.
$ LC_ALL=fr_FR.UTF-8 ./yash -c 'a=$((1e-2)); echo $(($a + 1))'
./yash: arithmetic: `,' is not a valid number or operator
마침표를 사용하는 스크립트에서 부동 소수점 상수를 사용할 수 있고 다른 로케일에서 작동을 멈출 까 걱정할 필요는 없지만 사용자가 오랫동안 표현한 숫자를 처리 할 수 있다는 점에서 좋습니다 당신이 기억하는대로 :
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
int=${float%.*}
Mac의 bash (버전 3.2.57 (1)-릴리스) 스크립트 (버전 10.13.4 (17E199))에서 매우 잘 작동했습니다.
,
10 진 기수 일 것입니다. 에 대한 섹션을 참조하십시오LC_ALL=C
bc
-임의 정밀도 계산기 언어
int (float)는 다음과 같아야합니다 :
$ echo "$float/1" | bc
1234
더 잘 사용하려면 다음을 사용하십시오.
$ echo "($float+0.5)/1" | bc
예:
$ float=1.49
$ echo "($float+0.5)/1" | bc
1
$ float=1.50
$ echo "($float+0.5)/1" | bc
2
float=-2; echo "($float+0.5)/1" | bc
제공합니다 -1
.
관련 :
@ Stéphane Chazelas awk
답변 보완 :
float_to_integer_rounding_nearst() {
awk 'BEGIN{for (i=1; i<ARGC;i++) printf "%.0f", ARGV[i]}' "$@";
}
float_to_integer_rounding_floor() {
awk 'BEGIN{for (i=1; i<ARGC;i++) printf "%d", int( ARGV[i] )}' "$@";
}
printf
또는 builtin보다 awk를 선호하는 다른 이유가 있는지 확실 하지 않습니다 printf
.