bash에서 bc를 사용하여 소수를 반올림하는 방법은 무엇입니까? -p “Press any

bash 스크립팅을 사용하여 원하는 것에 대한 간단한 예 :

#!/bin/bash
echo "Insert the price you want to calculate:"
read float
echo "This is the price without taxes:"
echo "scale=2; $float/1.18" |bc -l
read -p "Press any key to continue..."
bash scriptname.sh

가격이 48.86이라고 가정하면 대답은 41.406779661입니다 (실제로 41.40을 사용하고 있기 때문에 scale=2;)

내 질문은 :
이 방법으로 답변을 표시하기 위해 두 번째 소수를 반올림하는 방법은 무엇입니까? : 41.41



답변

bash round 함수 :

round()
{
echo $(printf %.$2f $(echo "scale=$2;(((10^$2)*$1)+0.5)/(10^$2)" | bc))
};

코드 예제에서 사용됩니다 :

#!/bin/bash
# the function "round()" was taken from 
# http://stempell.com/2009/08/rechnen-in-bash/

# the round function:
round()
{
echo $(printf %.$2f $(echo "scale=$2;(((10^$2)*$1)+0.5)/(10^$2)" | bc))
};

echo "Insert the price you want to calculate:"
read float
echo "This is the price without taxes:"
#echo "scale=2; $float/1.18" |bc -l
echo $(round $float/1.18 2);
read -p "Press any key to continue..."

행운을 빕니다 : O)


답변

가장 간단한 해결책 :

printf %.2f $(echo "$float/1.18" | bc -l)


답변

배쉬 / awk 반올림 :

echo "23.49" | awk '{printf("%d\n",$1 + 0.5)}'  

파이썬이 있다면 다음과 같은 것을 사용할 수 있습니다 :

echo "4.678923" | python -c "print round(float(raw_input()))"


답변

순전히 bc 솔루션이 있습니다. 반올림 규칙 : +/- 0.5에서 0에서 반올림합니다.

찾고있는 스케일을 $ result_scale에 넣으십시오. bc 명령 목록에서 $ MATH 위치에 수학이 있어야합니다.

bc <<MATH
h=0
scale=0

/* the magnitude of the result scale */
t=(10 ^ $result_scale)

/* work with an extra digit */
scale=$result_scale + 1

/* your math into var: m */
m=($MATH)

/* rounding and output */
if (m < 0) h=-0.5
if (m > 0) h=0.5

a=(m * t + h)

scale=$result_scale
a / t
MATH


답변

나는 그것이 오래된 질문이라는 것을 알고 있지만 ‘if’나 가지가없는 순수한 ‘bc’- 솔루션이 있습니다.

#!/bin/sh
bcr()
{
    echo "scale=$2+1;t=$1;scale-=1;(t*10^scale+((t>0)-(t<0))/2)/10^scale" | bc -l
}

bcr '2/3' 5또는 bcr '0.666666' 2-> 와 같이 사용하십시오 (표현식과 스케일)

C / C ++와 같은 bc에서는 계산에 논리 표현식을 혼합 할 수 있기 때문에 가능합니다. 표현식 ((t>0)-(t<0))/2)은 ‘t’의 부호에 따라 +/- 0.5로 평가되므로 반올림에 올바른 값을 사용합니다.


답변

#!/bin/bash
# - loosely based on the function "round()", taken from 
# http://stempell.com/2009/08/rechnen-in-bash/

# - inspired by user85321 @ askubuntu.com (original author)
#   and Aquarius Power

# the round function (alternate approach):

round2()
{
    v=$1
    vorig=$v
    # if negative, negate value ...
    (( $(bc <<<"$v < 0") == 1 )) && v=$(bc <<<"$v * -1")
    r=$(bc <<<"scale=$3;(((10^$3)*$v/$2)+0.5)/(10^$3)")

    # ... however, since value was only negated to get correct rounding, we 
    # have to add the minus sign again for the resulting value ...

    (( $(bc <<< "$vorig < 0") == 1 )) && r=$(bc <<< "$r * -1")
    env printf %.$3f $r
};

echo "Insert the price you want to calculate:"
read float
echo "This is the price without taxes:"
round2 $float 1.18 2
echo && read -p "Press any key to continue..."

실제로 간단합니다. 음수에 대해 하드 코딩 된 “-0.5″변형을 명시 적으로 추가 할 필요가 없습니다. 수학적으로 말, 우리는 단지 계산거야 절대 값 인수를 여전히 추가 우리가 평소대로 0.5. 그러나 (불행히도) abs()우리가 처리 할 때 내장 함수 가 없기 때문에 ( 코드를 작성하지 않는 한) 단순히 부정 할 것입니다 인수가 부정적이라면 입니다.

또한 을 매개 변수로 사용하는 것은 매우 번거로운 것으로 판명되었습니다 (내 솔루션 때문에 배당 자와 제수에 별도로 액세스 할 수 있어야합니다). 이것이 내 스크립트에 추가 세 번째 매개 변수가있는 이유입니다.


답변

bc함수 내에서 하나의 값만 반올림하는 방법 에 대한 순수한 대답을 찾고 있지만 순수한 bash대답은 다음과 같습니다.

#!/bin/bash

echo "Insert the price you want to calculate:"
read float
echo "This is the price without taxes:"

embiggen() {
  local int precision fraction=""
  if [ "$1" != "${1#*.}" ]; then  # there is a decimal point
    fraction="${1#*.}"       # just the digits after the dot
  fi
  int="${1%.*}"              # the float as a truncated integer
  precision="${#fraction}"   # the number of fractional digits
  echo $(( 10**10 * $int$fraction / 10**$precision ))
}

# round down if negative
if [ "$float" != "${float#-}" ]
  then round="-5000000000"
  else round="5000000000"
fi

# calculate rounded answer (sans decimal point)
answer=$(( ( `embiggen $float` * 100 + $round ) / `embiggen 1.18` ))

int=${answer%??}  # the answer as a truncated integer

echo $int.${answer#$int}  # reassemble with correct precision

read -p "Press any key to continue..."

기본적으로 이것은 소수점을 조심스럽게 추출하고 모든 것을 1,000 억 (10¹ 10**10in bash)으로 곱하고 정밀도와 반올림을 조정하고 실제 나누기를 수행하고 적절한 크기로 다시 나누고 소수점을 다시 삽입합니다.

단계별 :

embiggen()함수는 잘린 정수 형식의 인수를 할당하고 $int에 점 다음에 숫자를 저장합니다 $fraction. 소수 자릿수는에 표시되어 $precision있습니다. 수학의 연결에 의해 곱 10¹⁰ $int$fraction후와 그 예는 (정밀도에 맞게 조정 embiggen 48.8610¹⁰ × 100분의 4,886 반환된다488600000000 488,600,000,000)입니다.

우리는 100 분의 1의 정밀도를 원하므로 첫 번째 숫자에 100을 곱하고 반올림 목적으로 5를 더한 다음 두 번째 숫자를 나눕니다. 이 임무는 $answer우리에게 최종 답변의 백 배 를 남깁니다.

이제 소수점을 추가해야합니다. 우리는 새로운 지정 $int에 가치를 $answer다음의 마지막 두 자리를 제외 echo점으로 그것을하고 $answer제외$int 이미 알아서 값을. (이것이 주석처럼 보이게하는 구문 강조 버그는 신경 쓰지 마십시오)

(Bashism : 지수화는 POSIX가 아니므로 이것은 bashism입니다. 순수한 POSIX 솔루션은 10의 거듭 제곱을 사용하는 대신 0을 추가하기 위해 루프를 필요로합니다. 또한 “embiggen”은 완벽하게 cromulant 단어입니다.)


zsh쉘로 사용하는 주된 이유 중 하나 는 부동 소수점 수학을 지원하기 때문입니다. 이 질문에 대한 해결책은 다음과 같이 매우 간단합니다 zsh.

printf %.2f $((float/1.18))

(누군가에서 부동 소수점 산술을 활성화하는 트릭 으로이 답변에 의견을 추가하고 싶지만 bash그러한 기능이 아직 존재하지 않는다는 것을 확신합니다.)