데이터 열의 최대값을 찾기 위해 gawk를 사용하려고 합니다.
gawk 'BEGIN{max=0} {if($1>0+max) max=$1} END {print max}' dataset.dat
다음과 같습니다 dataset.dat
.
2.0
2.0e-318
명령의 출력은 다음과 같습니다.
2.0e-318
당연히 2보다 작습니다.
내 실수는 어디에 있습니까?
편집하다
흥미롭게도 입력 파일의 행을 바꾸면 출력은 다음과 같습니다.
2.0
편집 2
내 gawk 버전은 GNU Awk 4.2.1, API: 2.0(GNU MPFR 4.0.2, GNU MP 6.1.2)입니다.
답변1
2e-318
awk에서는 이러한 작은 숫자( )를 처리하는 데 몇 가지 문제가 있습니다.
먼저, 입력을 사용하기 전에 숫자로 변환해야 합니다. 이는 일반적으로 0을 추가하여 수행됩니다. 따라서 다음과 같은 것이 필요합니다.
val=0+$1
2. 일반 배정밀도 부동 소수점 숫자(53비트 가수 및 11비트 지수)지수의 11비트 너비를 사용하면 10e-308에서 10e308 사이의 숫자를 표현할 수 있습니다.따라서 일반 부동 소수점 숫자는 이러한 숫자를 표현할 수 없습니다.
$ echo '1e-307 1e-308' | awk '{print $1,$1+0,$2,$2+0}' 1e-307 1e-307 1e-308 0
기본적으로 GNU awk는 다음 (일반) 값을 허용하지 않습니다
1e-308
.셋째, 기본 변환 형식(CNVFMT 및 OFMT)
awk
은 으로 설정됩니다"%.6g"
. 유효 숫자가 6개를 초과하는 숫자는 잘립니다. 더 중요한 번호를 확인하려면 요청하세요. 15 와 같습니다%.15g
(53자리 가수에 17 이상을 요구하지 마십시오. 거짓말을 할 수도 있습니다).max
넷째, 첫 번째 입력에 첫 번째 값을 설정하는 것이 좋습니다 . 입력 최대값이 음수이면 최대값을 0으로 설정하면 실패합니다.
GNU awk를 사용하고 임의의 정밀도로 컴파일된 경우 다음을 사용할 수 있습니다.
$ printf '%s\n' 2e-318 2e-317 2e-307 2e-308 2e-319 |
awk -M -v PREC=100 'BEGIN{OFMT="%.15g"};
{val=0+$1};
NR==1{max=val};
{print($1,val,max)};
val>max{max=val}
END{print max}'
2e-318 2e-318 2e-318
2e-317 2e-317 2e-318
2e-307 2e-307 2e-317
2e-308 2e-308 2e-307
2e-319 2e-319 2e-307
2e-307
또는 사용 사례에 맞게 단순화되었습니다.
awk -M -v PREC=100 '
BEGIN{OFMT="%.15g"}; # allow more than 6 figures
{val=0+$1}; # convert input to a (float) number.
NR==1{max=val}; # On the first line, set the max value.
val>max{max=val} # On every entry keep track of the max.
END{print max} # At the end, print the max.
' file # file with input (one per line).
답변2
숫자 변환을 강제하려면 각 $1의 접두사로 0+가 필요합니다. max에는 0+가 필요하지 않습니다. 저장 시 이미 숫자로 변환되었습니다.
Paul--) AWK='
> BEGIN { max = 0; }
> 0+$1 > max { max = 0 + $1; }
> END { print max; }
> '
Paul--) awk "${AWK}" <<[][]
> 2.0
> 2.0e-318
> [][]
2
Paul--) awk "${AWK}" <<[][]
> 2.0e-318
> 2.0
> [][]
2