bash에서 부동소수점 산술을 어떻게 사용합니까?
Bash 스크립트에서 두 개의 이미지 폭을 나누려고 하는데 bash가 표시됩니다.0
결과적으로:
RESULT=$(($IMG_WIDTH/$IMG2_WIDTH))
저는 배시 가이드를 공부했고 제가 사용해야 한다는 것을 알고 있습니다.bc
은 인넷의모예그에사들다용니합은서터든다니▁in를 사용합니다.bc
echo
나는 같은 것을 내 안에 넣으려고 노력했습니다.SCALE
하지만 그것은 작동하지 않았다.
튜토리얼에서 찾은 예는 다음과 같습니다.
echo "scale=2; ${userinput}" | bc
어떻게 하면 배시가 나에게 그런 플로트를 줄 수 있습니까?0.5
?
할 수 없습니다. bash는 정수만 수행합니다. 다음과 같은 도구에 위임해야 합니다.bc
.
다음을 수행할 수 있습니다.
bc <<< 'scale=2; 100/3'
33.33
UPDATE 20130926
사용할 수 있는 항목:
bc -l <<< '100/3' # saves a few hits
33.33333333333333333333
때리기
다른 사람들이 지적했듯이,bash
에서는 부동 두 부 동 소 산 점 지 하 않 지 지 예 들 두 개 를 소 어 의 사 하 산 는 용 있 수 일 여 니 습 다 소 가 고 할 트 장 로 으 릭 만 점 수 부 정 술 을 수 수 점 을술원▁trick▁doesim▁ar,▁point▁decals▁two▁some▁it있니다ithmeticery:는▁with▁decimal습▁fake,▁floating▁you수▁fixed동▁e
echo $(( 100 * 1 / 3 )) | sed -e 's/..$/.&/;t' -e 's/.$/.0&/'
출력:
.33
비슷하지만 보다 간결한 접근법은 닐프레드의 답변을 참조하십시오.
대안
언급된 것 외에bc
그리고.awk
대안은 또한 다음과 같습니다.
바삭바삭한
clisp -x '(/ 1.0 3)'
정리된 출력:
clisp --quiet -x '(/ 1.0 3)'
또는을통여를 통해stdin
:
echo '(/ 1.0 3)' | clisp --quiet | tail -n1
dc
echo 2k 1 3 /p | dc
천재 cli 계산기
echo 1/3.0 | genius
유령 대본
echo 1 3 div = | gs -dNODISPLAY -dQUIET | sed -n '1s/.*>//p'
그누플롯
echo 'pr 1/3.' | gnuplot
이미지매직
convert xc: -format '%[fx:1/3]' info:
또는을통여를 통해stdin
:
echo 1/3 | { convert xc: -format "%[fx:$(cat)]" info:; }
제이큐
jq -n 1/3
또는을통여를 통해stdin
:
echo 1/3 | jq -nf /dev/stdin
크쉬
echo 'print $(( 1/3. ))' | ksh
루아
lua -e 'print(1/3)'
또는 stdin을 통해:
echo 'print(1/3)' | lua
격언
echo '1/3,numer;' | maxima
정리된 출력:
echo '1/3,numer;' | maxima --quiet | sed -En '2s/[^ ]+ [^ ]+ +//p'
노드
echo 1/3 | node -p
옥타브
echo 1/3 | octave
펄
echo print 1/3 | perl
파이썬2
echo print 1/3. | python2
파이썬3
echo 'print(1/3)' | python3
R
echo 1/3 | R --no-save
정리된 출력:
echo 1/3 | R --vanilla --quiet | sed -n '2s/.* //p'
루비의
echo puts 1/3.0 | ruby
단위들
units 1/3
콤팩트 출력:
units --com 1/3
wcalc
echo 1/3 | wcalc
정리된 출력:
echo 1/3 | wcalc | tr -d ' ' | cut -d= -f2
zsh
print $(( 1/3. ))
또는을통여를 통해stdin
:
echo 'print $(( 1/3. ))' | zsh
기타 출처
스테판 샤젤라스는 UL에 대한 비슷한 질문에 답했습니다.
마빈의 답변을 조금 개선합니다.
RESULT=$(awk "BEGIN {printf \"%.2f\",${IMG_WIDTH}/${IMG2_WIDTH}}")
bc는 항상 설치된 패키지로 제공되지 않습니다.
당신은 bc by the를 사용할 수 있습니다.-l
문자은(L 문자)입니다.
RESULT=$(echo "$IMG_WIDTH/$IMG2_WIDTH" | bc -l)
bc의 대안으로 스크립트 내에서 awk를 사용할 수 있습니다.
예:
echo "$IMG_WIDTH $IMG2_WIDTH" | awk '{printf "%.2f \n", $1/$2}'
위에서 "%.2f"는 소수점 뒤에 두 자리 숫자가 있는 부동 소수점 번호를 반환하도록 printf 함수에 지시합니다.awk가 제대로 작동하기 때문에 필드로 변수를 파이프로 연결하기 위해 에코를 사용했습니다.$1"과 "$2"는 awk에 입력된 첫 번째와 두 번째 필드를 나타냅니다.
다음을 사용하여 결과를 다른 변수로 저장할 수 있습니다.
RESULT = `echo ...`
플로트 이전에는 고정 소수점 논리가 사용되었습니다.
IMG_WIDTH=100
IMG2_WIDTH=3
RESULT=$((${IMG_WIDTH}00/$IMG2_WIDTH))
echo "${RESULT:0:-2}.${RESULT: -2}"
33.33
마지막 줄은 bashim입니다. bash를 사용하지 않는 경우 대신 다음 코드를 사용하십시오.
IMG_WIDTH=100
IMG2_WIDTH=3
INTEGER=$(($IMG_WIDTH/$IMG2_WIDTH))
DECIMAL=$(tail -c 3 <<< $((${IMG_WIDTH}00/$IMG2_WIDTH)))
RESULT=$INTEGER.$DECIMAL
echo $RESULT
33.33
코드 뒤에 있는 근거는 다음과 같습니다. 나누기 전에 100을 곱하면 소수 2개를 얻을 수 있습니다.
부동 소수점 연산을 포함한 많은 추가적인 기능이 있는 (거의) 배시 슈퍼 세트인 zsh를 시도하기에 완벽한 시간입니다.다음은 zsh의 예제입니다.
% IMG_WIDTH=1080
% IMG2_WIDTH=640
% result=$((IMG_WIDTH*1.0/IMG2_WIDTH))
% echo $result
1.6875
이 게시물은 도움이 될 수 있습니다: bash - 일상적인 사용을 위해 zsh로 바꿀 가치가 있습니까?
원하는 변형을 찾은 경우 함수로 래핑할 수도 있습니다.
여기서 저는 바시즘을 디비 함수로 포장하고 있습니다.
라이너 하나:
function div { local _d=${3:-2}; local _n=0000000000; _n=${_n:0:$_d}; local _r=$(($1$_n/$2)); _r=${_r:0:-$_d}.${_r: -$_d}; echo $_r;}
또는 다중 선:
function div {
local _d=${3:-2}
local _n=0000000000
_n=${_n:0:$_d}
local _r=$(($1$_n/$2))
_r=${_r:0:-$_d}.${_r: -$_d}
echo $_r
}
이제 당신은 기능을 가지고 있습니다.
div <dividend> <divisor> [<precision=2>]
그리고 그것을 처럼 사용합니다.
> div 1 2
.50
> div 273 123 5
2.21951
> x=$(div 22 7)
> echo $x
3.14
업데이트 Bash에 대한 부동 소수점 번호와 함께 기본 작업을 제공하는 작은 스크립트를 추가했습니다.
용도:
> add 1.2 3.45
4.65
> sub 1000 .007
999.993
> mul 1.1 7.07
7.7770
> div 10 3
3.
> div 10 3.000
3.333
여기 대본이 있습니다.
#!/bin/bash
__op() {
local z=00000000000000000000000000000000
local a1=${1%.*}
local x1=${1//./}
local n1=$((${#x1}-${#a1}))
local a2=${2%.*}
local x2=${2//./}
local n2=$((${#x2}-${#a2}))
local n=$n1
if (($n1 < $n2)); then
local n=$n2
x1=$x1${z:0:$(($n2-$n1))}
fi
if (($n1 > $n2)); then
x2=$x2${z:0:$(($n1-$n2))}
fi
if [ "$3" == "/" ]; then
x1=$x1${z:0:$n}
fi
local r=$(($x1"$3"$x2))
local l=$((${#r}-$n))
if [ "$3" == "*" ]; then
l=$(($l-$n))
fi
echo ${r:0:$l}.${r:$l}
}
add() { __op $1 $2 + ;}
sub() { __op $1 $2 - ;}
mul() { __op $1 $2 "*" ;}
div() { __op $1 $2 / ;}
bash에서 부동 소수점 계산을 수행하는 방법:
"here strings"를 사용하는 대신 (<<<
)와 함께 께함와께bc
명령, 가장 많이 투표된 예 중 하나가 그러하듯이, 여기 내가 가장 좋아하는 것이 있습니다.bc
부소점예제서, 에쪽른오 바로 EXAMPLES
의한부의 한 bc
페이지 페참이지조▁man참 (남자) 참조)man bc
(매뉴얼 페이지의 경우).
은 다음과 pi = 4*atan(1)
.a()
는 아는입니다.bc
에 대한 수학 atan()
.
다음은 부동소수점 계산 결과를 bash 변수에 저장하는 방법입니다. 이 경우는 다음과 같은 변수에 저장합니다.
scale=10
이 경우 정밀도의 소수 자릿수를 10으로 설정합니다.이 플레이스 이후의 모든 소수 자릿수는 잘립니다.pi=$(echo "scale=10; 4*a(1)" | bc -l)
한 , 이, 이변의값출코드는한력줄다가다음같지니추제가합이과면려을도하수▁the▁add▁that▁now,▁simply,▁of다이▁to니제추를 추가하기만 하면 됩니다.
echo
다음과 같은 후속 명령으로 끝까지 명령합니다.명령에 따라 소수점 이하 10자리에서 절단을 기록합니다.pi=$(echo "scale=10; 4*a(1)" | bc -l); echo $pi 3.1415926532
마지막으로, 반올림을 좀 해보죠.여기서는 다음을 사용합니다.
printf
소수점 이하 4자리로 반올림하는 함수입니다.로 고는 다음과 .3.14159...
은 로진회로 합니다.3.1416
우리는 반올림 중이기 때문에 더 이상 사용할 필요가 없습니다.scale=10
소수점 이하 10자리로 자르기 때문에 그 부분만 제거하겠습니다.최종 솔루션은 다음과 같습니다.pi=$(printf %.4f $(echo "4*a(1)" | bc -l)); echo $pi 3.1416
위의 기술에 대한 또 다른 훌륭한 응용 프로그램과 데모가 있습니다: 런타임 측정 및 인쇄입니다.
(여기에 있는 다른 답변도 참조하십시오.)
:dt_min
됨림올에서 됩니다.0.01666666666...
0.017
:
start=$SECONDS; sleep 1; end=$SECONDS; dt_sec=$(( end - start )); dt_min=$(printf %.3f $(echo "$dt_sec/60" | bc -l)); echo "dt_sec = $dt_sec; dt_min = $dt_min"
dt_sec = 1; dt_min = 0.017
관련:
- [내 대답] https://unix.stackexchange.com/questions/52313/how-to-get-execution-time-of-a-script-effectively/547849#547849
- [내 질문] 왼쪽 대괄호 세 개('<')는 bash에서 무엇을 의미합니까?
- https://unix.stackexchange.com/questions/80362/what-does-mean/80368#80368
- https://askubuntu.com/questions/179898/how-to-round-decimals-using-bc-in-bash/574474#574474
Bash에서는 부동 소수점 분할을 사용할 수 없지만 고정 소수점 분할을 사용할 수 있습니다.정수에 10의 거듭제곱을 곱한 다음 정수 부분을 분할하고 모듈로 연산을 사용하여 분수 부분을 구하는 것이 전부입니다.필요에 따라 반올림합니다.
#!/bin/bash
n=$1
d=$2
# because of rounding this should be 10^{i+1}
# where i is the number of decimal digits wanted
i=4
P=$((10**(i+1)))
Pn=$(($P / 10))
# here we 'fix' the decimal place, divide and round tward zero
t=$(($n * $P / $d + ($n < 0 ? -5 : 5)))
# then we print the number by dividing off the interger part and
# using the modulo operator (after removing the rounding digit) to get the factional part.
printf "%d.%0${i}d\n" $(($t / $P)) $(((t < 0 ? -t : t) / 10 % $Pn))
오래된 것은 알지만, 너무 유혹적입니다.그래서, 답은: 당신은 할 수 없습니다.하지만 당신은 할 수 있어요.시도해 보겠습니다.
$IMG_WIDTH=1024
$IMG2_WIDTH=2048
$RATIO="$(( IMG_WIDTH / $IMG2_WIDTH )).$(( (IMG_WIDTH * 100 / IMG2_WIDTH) % 100 ))"
이와 같이, 순수한 bash(다른 프로세스를 시작할 필요가 없음)에서 점 다음에 2자리 숫자가 나옵니다.물론, 만약 당신이 점 뒤에 한 자리만 필요하다면 당신은 10을 곱하고 모듈로 10을 합니다.
이 기능:
- 번째
$((...))
정수 나눗셈을 수행합니다. - 번째
$((...))
100배 더 큰 것에서 정수 나눗셈을 하고, 본질적으로 두 자리를 포인트의 왼쪽으로 이동합니다. 그러면 (%
으로써 두 수 있습니다 모듈로를 하면 두 자리만 얻을 수 있습니다.
보너스 트랙:bc
은 내에서 1 반면 한 x 1000은 1.8초가 걸렸습니다.bash
하나는 0.016초가 걸렸습니다.
사실 부동소수점은 아니지만 bc를 한 번 호출할 때 둘 이상의 결과를 설정하는 것을 원한다면...
source /dev/stdin <<<$(bc <<< '
d='$1'*3.1415926535897932384626433832795*2
print "d=",d,"\n"
a='$1'*'$1'*3.1415926535897932384626433832795
print "a=",a,"\n"
')
echo bc radius:$1 area:$a diameter:$d
반경이 $1로 표시된 원의 면적과 직경을 계산합니다.
bc를 사용할 수 없는 시나리오가 있습니다. bc가 단순히 존재하지 않을 수 있기 때문입니다. 예를 들어 일부 축소 버전의 비지박스 또는 임베디드 시스템과 같습니다.어떤 경우든 외부 종속성을 제한하는 것은 항상 좋은 일이므로, (숫자)로 나누는 숫자에 항상 0을 추가할 수 있습니다. 이는 10의 거듭제곱(필요한 정밀도에 따라 10의 거듭제곱을 선택해야 함)과 같습니다. 따라서 분할 출력이 정수가 됩니다.정수를 문자열로 처리하고 소수점(오른쪽에서 왼쪽으로 이동)을 배치하면 분자의 거듭제곱과 동일한 횟수만큼 분자를 곱합니다.이것은 정수 숫자만 사용하여 부동 결과를 얻는 간단한 방법입니다.
허용된 답변으로 백분율을 계산하려고 하지만 정확도가 떨어지는 경우:
실행할 경우:
echo "scale=2; (100/180) * 180" | bc
당신은.99.00
정확성을 잃고 있는 것뿐입니다.
이러한 방식으로 실행하는 경우:
echo "result = (100/180) * 180; scale=2; result / 1" | bc -l
이제 당신은99.99
.
인쇄하는 순간에만 스케일링을 하기 때문입니다.
여기를 참조
계산을 사용합니다.제가 찾은 것 중 가장 쉬운 예는 다음과 같습니다.
계산 1+1
2
계산 1/10
0.1
bash/shell의 주입 안전 부동 소수점 연산 **
참고: 이 답변의 초점은 bash(또는 다른 셸)에서 수학을 수행하기 위한 주입 안전 솔루션에 대한 아이디어를 제공하는 것입니다.물론 고급 문자열 처리 등을 수행하기 위해 약간의 조정과 함께 동일하게 사용할 수 있습니다.
제시된 솔루션의 대부분은 외부 데이터(변수, 파일, 명령줄, 환경 변수)를 사용하여 작은 스크립트릿을 즉시 구성합니다.외부 입력은 엔진에 악의적인 코드를 주입하는 데 사용될 수 있으며, 그 중 많은 코드를 주입합니다.
아래는 다양한 언어를 사용하여 기본적인 수학 계산을 수행하는 방법을 비교한 것으로, 결과는 부동 소수점이 됩니다.A + B * 0.1(부동점)을 계산합니다.
모든 솔루션은 유지 관리가 매우 어려운 동적 스크립트릿을 생성하지 않도록 합니다. 대신 정적 프로그램을 사용하고 지정된 변수에 매개 변수를 전달합니다.특수 문자가 포함된 매개 변수를 안전하게 처리하여 코드 주입 가능성을 줄입니다.입력/출력 기능을 제공하지 않는 'BC'는 예외입니다.
예외적으로 'bc'는 입력/출력을 제공하지 않으며 모든 데이터는 stdin의 프로그램을 통해 전송되며 모든 출력은 stdout으로 이동합니다.모든 계산이 샌드박스에서 실행되고 있어 부작용(파일 열기 등)이 발생하지 않습니다.이론적으로, 주입은 설계상 안전합니다!
A=5.2
B=4.3
# Awk: Map variable into awk
# Exit 0 (or just exit) for success, non-zero for error.
#
awk -v A="$A" -v B="$B" 'BEGIN { print A + B * 0.1 ; exit 0}'
# Perl
perl -e '($A,$B) = @ARGV ; print $A + $B * 0.1' "$A" "$B"
# Python 2
python -c 'import sys ; a = float(sys.argv[1]) ; b = float(sys.argv[2]) ; print a+b*0.1' "$A" "$B"
# Python 3
python3 -c 'import sys ; a = float(sys.argv[1]) ; b = float(sys.argv[2]) ; print(a+b*0.1)' "$A" "$B"
# BC
bc <<< "scale=1 ; $A + $B * 0.1"
다른 사람들이 지적했듯이 bash에는 부동 소수점 연산자가 내장되어 있지 않습니다.
bc, awk와 같은 계산기 프로그램이나 외부 프로그램을 사용하지 않아도 bash에서 부동소수점을 구현할 수 있습니다.
저는 제 프로젝트인 셸수학에서 정확히 이것을 세 가지 기본 단계로 수행하고 있습니다.
- 숫자를 정수 부분과 분수 부분으로 나눕니다.
- 내장된 정수 연산자를 사용하여 부품을 개별적으로 처리하는 동시에 장소 값과 운반에 주의합니다.
- 결과 재조합
티저로 x=0을 중심으로 한 테일러 시리즈를 사용하여 e를 계산하는 데모 스크립트를 추가했습니다.
시간이 있으시면 확인 부탁드립니다.당신의 피드백을 환영합니다!
Bash는 다른 프로그램 없이도 부동 소수점 결과를 계산할 수 있습니다.
Bash는 독립적으로 소수점 9번째 자리까지 π를 정확하게 계산할 수 있습니다.
예:
calc=104348/33215
accuracy=9
calc99p9=$((10**$accuracy))*$calc
result99p9=$((calc99p9))
result=${result99p9: -${#result99p9}: -$accuracy}.${result99p9: -$accuracy}
echo Bash calculated pi to be $result
의 결과.
Bash calculated pi to be 3.141592653
배당금 = 배당금 × 몫 + 잔여금
그냥 몫과 나머지를 계산해 봅시다.변수에 문자열을 연결합니다.
log_decimal divisor에만 유효한 새로운 방법:
function main() {
bar=10030
divisor=100
# divisor=50
quotient=$((bar / divisor))
# remainder=$((bar - v_int * divisor))
remainder=$((bar % divisor))
remainder_init=$remainder
printf "%-15s --> %s\n" "quotient" "$quotient"
printf "%-15s --> %s\n" "remainder" "$remainder"
cnt=0
while :; do
remainder=$((remainder * 10))
aux=$((remainder / divisor))
printf "%-15s --> %s\n" "aux" "$aux"
[[ aux -ne 0 ]] && break
((cnt += 1))
printf "%-15s --> %s\n" "remainder" "$remainder"
done
printf "%-15s --> %s\n" "cnt" "$cnt"
printf "%-15s --> %s\n" "aux" "$aux"
printf $quotient
printf "."
for i in $(seq 1 $cnt); do printf "0"; done
printf $remainder_init
}
clear
main
오래된 잘못된 방법:
bar=1234 \
&& divisor=1000 \
&& foo=$(printf "%s.%s" $(( bar / divisor )) $(( bar % divisor ))) \
&& printf "bar is %d miliseconds or %s seconds\n" $bar $foo
출력:bar is 1234 miliseconds or 1.234 seconds
다음은 awk 명령입니다: -F = 필드 구분 기호 == +
echo "2.1+3.1" | awk -F "+" '{print ($1+$2)}'
출력을 얼마나 정확하게 해야 합니까? 빈을 통한 근사치가 사용 사례에 이미 허용되는 경우 한 단계 더 나아가 POSIX 종료 코드 [0:256](다른 모든 정수는 해당 범위로 다시)를 활용할 수 있습니다.
예: gawk/nawk/mawk-1에서는 이미 정수 수준까지 에포크초를 제공하지만 밀리초에 가까운 정밀도를 추출하도록 확장하고 싶었지만 너무 현학적이지는 않았습니다. POSIX 셸에서 이 명령을 실행합니다.
exit $(( 10#` gdate +%5N ` * 256 / 100000 ))
다음을 나타내는 5자리 정수를 직접 할당합니다.0.xxxxxx
를 빈 중 256개의 빈을 실행 합니다.256
는 단가일종코얻습다니드의 .system()
호출합니다. 즉, 선택한 빈 번호입니다.저는 이 접근 방식이 전체 getline 호출을 사용하는 것보다 오버헤드가 낮다는 것을 알게 되었습니다.
또한 이 방법은 추가 단자를 출력하는 대신 출력을 POSIX 종료 코드로 직접 캡처합니다.
쉘 (셸산술))auto floors it to integer
* 0.0256) 대신 이런 식으로 쓰면 됩니다.어색한 기능으로 합하면, 이것과 비슷할 것입니다. 그10#
는 "01733"을 8진수로 해석하는 posix 쉘을 방지하기 위해 base-10을 강제하는 것입니다.
function msecs() { # n x 2**-8 = n divided by 256
return 2^-8 * \
system( "exit \44\50\50 " \
" 10\43\140 gdate \53" \
"%5N\140 \52 " \
"256 \57 100000 \51\51" )
}
- 나만의 코드를 위해, 나는 껍질 벗기기를 설명하기 위해 0.6%의 이발을 더 적용합니다.
n개의 배열 요소의 평균을 찾으려면 예를 들어 보겠습니다(물론 평균은 부동소수점/소수점).
declare -a arr
echo "How many numbers you want to enter?"
read n
echo "Enter the Array Elements"
for(( i=0 ; i<$n ; i++))
do
read array_elements
arr[$i]="$array_elements"
done
sum=0
for i in "${arr[@]}"
do
#sum and avg
sum=$(($sum + $i))
#average will come in decimals
avg=`echo $sum / $n | bc -l`
done
# Output results:
printf "Average of Array Elements %.2f:" $avg
따라서 "| bc-l"을 사용하여 부동 계산을 수행합니다.
언급URL : https://stackoverflow.com/questions/12722095/how-do-i-use-floating-point-arithmetic-in-bash
'programing' 카테고리의 다른 글
현재 분기에 대한 추적 정보가 없습니다. (0) | 2023.05.03 |
---|---|
배치 스크립트를 사용하여 디렉토리의 각 파일에 작업을 수행하는 방법 (0) | 2023.05.03 |
cmd 단위로 간단한 파일 검색을 수행하는 방법 (0) | 2023.04.28 |
IIS Express용 web.config에 MIME 매핑 추가 (0) | 2023.04.28 |
node.js에서 path.join을 사용해야 합니까? (0) | 2023.04.28 |