답변:
정수 부분과 분수 부분을 별도로 확인할 수 있습니다.
#!/bin/bash
min=12.45
val=12.35
if (( ${val%%.*} < ${min%%.*} || ( ${val%%.*} == ${min%%.*} && ${val##*.} < ${min##*.} ) )) ; then
min=$val
fi
echo $min
주석에서 언급했듯이 두 숫자에 소수 부분이 있고 두 소수 부분에 동일한 자릿수가있는 경우에만 작동합니다. 다음은 정수 또는 분수 및 모든 bash 연산자에서 작동하는 버전입니다.
#!/bin/bash
shopt -s extglob
fcomp() {
local oldIFS="$IFS" op=$2 x y digitx digity
IFS='.' x=( ${1##+([0]|[-]|[+])}) y=( ${3##+([0]|[-]|[+])}) IFS="$oldIFS"
while [[ "${x[1]}${y[1]}" =~ [^0] ]]; do
digitx=${x[1]:0:1} digity=${y[1]:0:1}
(( x[0] = x[0] * 10 + ${digitx:-0} , y[0] = y[0] * 10 + ${digity:-0} ))
x[1]=${x[1]:1} y[1]=${y[1]:1}
done
[[ ${1:0:1} == '-' ]] && (( x[0] *= -1 ))
[[ ${3:0:1} == '-' ]] && (( y[0] *= -1 ))
(( ${x:-0} $op ${y:-0} ))
}
for op in '==' '!=' '>' '<' '<=' '>='; do
fcomp $1 $op $2 && echo "$1 $op $2"
done
1.00000000000000000000000001
보다 크다 2
.
간단한 조작을 위해 패키지 num-utils 를 사용할 수 있습니다 ...
더 심각한 수학에 대해서는 이 링크를 참조하십시오 . 예를 들어 몇 가지 옵션을 설명합니다.
의 예 numprocess
echo "123.456" | numprocess /+33.267,%2.33777/
# 67.0395291239087
A programs for dealing with numbers from the command line
The 'num-utils' are a set of programs for dealing with numbers from the
Unix command line. Much like the other Unix command line utilities like
grep, awk, sort, cut, etc. these utilities work on data from both
standard in and data from files.
Includes these programs:
* numaverage: A program for calculating the average of numbers.
* numbound: Finds the boundary numbers (min and max) of input.
* numinterval: Shows the numeric intervals between each number in a sequence.
* numnormalize: Normalizes a set of numbers between 0 and 1 by default.
* numgrep: Like normal grep, but for sets of numbers.
* numprocess: Do mathematical operations on numbers.
* numsum: Add up all the numbers.
* numrandom: Generate a random number from a given expression.
* numrange: Generate a set of numbers in a range expression.
* numround: Round each number according to its value.
여기에 bash
해킹이 있습니다 ... 문자열을 왼쪽에서 오른쪽으로 비교하기 위해 정수에 선행 0을 추가합니다. 이 특정 코드 조각은 min 과 val 모두 실제로 소수점과 하나 이상의 10 진수를 가져야합니다.
min=12.45
val=10.35
MIN=0; VAL=1 # named array indexes, for clarity
IFS=.; tmp=($min $val); unset IFS
tmp=($(printf -- "%09d.%s\n" ${tmp[@]}))
[[ ${tmp[VAL]} < ${tmp[MIN]} ]] && min=$val
echo min=$min
산출:
min=10.35
부동 소수점 숫자 (+-* / 및 비교)에 대한 간단한 계산을 위해 awk를 사용할 수 있습니다.
min=$(echo 12.45 10.35 | awk '{if ($1 < $2) print $1; else print $2}')
또는 ksh93 또는 zsh (bash가 아닌)를 사용하는 경우 부동 소수점 숫자를 지원하는 쉘의 내장 산술을 사용할 수 있습니다.
if ((min>val)); then ((val=min)); fi
고급 부동 소수점 계산에 대해서는 bc를 찾아보십시오 . 실제로 임의의 정밀도 수정 점 번호에서 작동합니다.
이 명령 sort
에는 최소값 또는 최대 값을 찾아 "보다 작음"또는 "보다 큼" 을 비교하는 데 사용할 수 있는 옵션 -g
( --general-numeric-sort
)이 있습니다 .<
>
이 예제는 최소값을 찾습니다.
$ printf '12.45\n10.35\n' | sort -g | head -1
10.35
전자 표기법과 같이 부동 소수점 숫자의 일반적인 표기법으로 작동합니다.
$ printf '12.45E-10\n10.35\n' | sort -g | head -1
12.45E-10
를 참고 E-10
첫 번째 숫자를 만드는 0.000000001245
미만 참 10.35
.
부동 소수점 표준 인 IEEE754 는 일부 특수 값을 정의합니다. 이러한 비교에서 흥미로운 것은 INF
무한대입니다. 음의 무한대도 있습니다. 둘 다 표준에서 잘 정의 된 값입니다.
$ printf 'INF\n10.35\n' | sort -g | head -1
10.35
$ printf '-INF\n10.35\n' | sort -g | head -1
-INF
최대 사용 찾으려면 sort -gr
대신을 sort -g
정렬 순서를 반대로 :
$ printf '12.45\n10.35\n' | sort -gr | head -1
12.45
<
( "보다 작음") 비교 를 구현하려면 if
등을 사용할 수 있으므로 최소값 중 하나와 비교하십시오. 텍스트와 비교 하여 최소값이 값과 같으면 다른 값보다 작습니다.
$ a=12.45; b=10.35
$ [ "$a" = "$(printf "$a\n$b\n" | sort -g | head -1)" ]
$ echo $?
1
$ a=12.45; b=100.35
$ [ "$a" = "$(printf "$a\n$b\n" | sort -g | head -1)" ]
$ echo $?
0
a == min(a, b)
동일하다 a <= b
. 이것이 덜 엄격하게 검사하지 않는다는 점은 주목할 가치가 있습니다. 당신이하고 싶은 경우에, 당신은 확인해야 할 a == min(a, b) && a != max(a, b)
otherwords에서,a <= b and not a >= b
부동 소수점 산술을 기본적으로 지원하는 ksh
( ksh93
정확하게) 또는를 사용하십시오 zsh
.
$ cat test.ksh
#!/bin/ksh
min=12.45
val=10.35
if (( $val < $min )) ; then
min=$val
fi
echo "$min"
$ ./test.ksh
10.35
편집 : 미안, ksh93
이미 보고 싶었습니다 . 첫 번째 질문에 게시 된 스크립트를 명확하게하기 위해 내 대답을 유지하면 셸 스위치 외부에서 변경하지 않고 사용할 수 있습니다.
Edit2 : ksh93
변수 내용이 로케일과 일치해야합니다 (예 : 프랑스어 로케일의 경우 점 대신 쉼표를 사용해야 함).
...
min=12,45
val=10,35
...
보다 강력한 해결책은 스크립트 시작 부분에 사용자의 로캘에 관계없이 작동하도록 로캘을 설정하는 것입니다.
...
export LC_ALL=C
min=12.45
val=10.35
...
.
하므로 소수점 구분 기호가 있는 세계에서는 절반이 아닙니다 ,
. zsh
그 문제가 없습니다.
LC_ALL
즉, 숫자가 사용자가 선호하는 형식으로 표시 (또는 입력)되지 않습니다. 더 나은 접근 방법 은 unix.stackexchange.com/questions/87745/what-does-lc-all-c-do/… 를 참조하십시오 .
.
어쨌든 가정 합니다.
min=$(echo "${min}sa ${val}d la <a p" | dc)
사용하는 dc
을 계산기 s
의 값을 찢고 $min
레지스터 a
와 d
값을 uplicates $val
주요 실행 스택의 상단에. 그런 다음 l
내용을 a
스택 상단에 흘려 보냅니다 .
${min} ${val} ${val}
이 <
스택은 스택에서 상위 2 개 항목을 팝하여 비교합니다. 따라서 스택은 다음과 같습니다.
${val}
맨 위 항목이 맨 위 항목보다 작 으면 맨 위에 내용을 푸시 a
하므로 스택은 다음과 같습니다.
${min} ${val}
그렇지 않으면 아무것도하지 않으며 스택은 여전히 다음과 같습니다.
${val}
그런 다음 p
상단 스택 항목을 헹구십시오.
그래서 당신의 문제를 위해 :
min=12.45
val=12.35
echo "${min}sa ${val}d la <a p" | dc
###OUTPUT
12.35
그러나:
min=12.45
val=12.55
echo "${min}sa ${val}d la <a p" | dc
###OUTPUT
12.45
오래되고 좋은 것을 사용하지 않는 이유 expr
않습니까?
구문 예 :
if expr 1.09 '>' 1.1 1>/dev/null; then
echo 'not greater'
fi
대한 진정한 표현, EXPR 종료 코드는 표준 출력으로 전송 문자열을 '1'로, 0입니다. 반대 잘못된 표현.
나는 이것을 GNU와 FreeBSD 8 expr로 점검했다.
expr 1.09 '<' -1.1
인쇄 1
하고 종료 0
합니다.
두 개의 (아마도 소수) 숫자가 순서대로 있는지 확인하려면 sort
(합리적으로) 이식 가능합니다.
min=12.45
val=12.55
if { echo $min ; echo $val ; } | sort -n -c 2>/dev/null
then
echo min is smallest
else
echo val is smallest
fi
그러나 실제로 최소값을 업데이트하려면을 필요로하지 않습니다 if
. 숫자를 정렬하고 항상 첫 번째 (최소) 숫자를 사용하십시오.
min=12.45
val=12.55
smallest=$({ echo $min ; echo $val ; } | sort -n | head -n 1)
echo $smallest
min=$smallest
일반적으로 파이썬 코드가 포함 된 비슷한 작업을 수행합니다.
#!/bin/sh
min=12.45
val=10.35
python - $min $val<<EOF
if ($min > $val):
print $min
else:
print $val
EOF
0.5
와 비교해보십시오0.06
). 이미 십진 표기법을 이해하는 도구를 사용하는 것이 좋습니다.