[unix] 부동 소수점 숫자를 정수로 변환하는 방법?

이것은 bash에서 부동 소수점을 정수로 변환하는 올바른 방법입니까? 다른 방법이 있습니까?

flotToint() {
    printf "%.0f\n" "$@"
}



답변

세게 때리다

에서 bash, 아마 그것이 얻는만큼 좋을 것입니다. 그것은 쉘 내장을 사용합니다. 변수에 결과가 필요한 경우 명령 대체 또는 bash특정을 사용할 수 있습니다 (이제도 지원합니다 zsh).

printf -v int %.0f "$float"

당신은 할 수 있습니다 :

float=1.23
int=${float%.*}

그러나 가장 가까운 정수를 제공하는 대신 분수 부분을 제거하면 $floatlike 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))"

(아래 참조).

POSIX

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

에서 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

그러나 doubles는 매우 큰 수를 나타낼 수 있지만 정수는 훨씬 더 제한적입니다.

$ printf '%.0f\n' 1e123
999999999999999977709969731404129670057984297594921577392083322662491290889839886077866558841507631684757522070951350501376
$ echo $((int(1e123)))
-9223372036854775808

ksh93

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


답변

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=1.23
int=${float%.*}

그러나 이것은 가장 가까운 정수를 제공하는 대신 분수 부분을 제거하고 1.2e9 또는 .12와 같은 $ float 값에는 작동하지 않습니다 …. “

그냥 사용하십시오 ${float%%.*}.

echo ${float%%.*}
1


답변

매우 간단한 해키 하나는

function float_to_int() {
  echo $1 | cut -d. -f1    # or use -d, if decimals separator is ,
}

샘플 출력

$ float_to_int 32.333
32
$ float_to_int 32
32


답변

관련 :

  1. awk에서 float를 정수로 만드는 방법 ,
  2. 쉘에서 부동 소수점 숫자를 반올림하는 방법은 무엇입니까?

@ 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] )}' "$@";
}


답변