bc를 올바르게 사용하여 백분율 값을 부동 소수점 형식으로 변환하는 방법은 무엇입니까?

bc를 올바르게 사용하여 백분율 값을 부동 소수점 형식으로 변환하는 방법은 무엇입니까?

3개의 변수와 값이 있습니다.

totalLines=14
outsideLines=6
multiplied=600

totalLines총 행 수(100%)를 나타내는 반면, outsideLines타임스탬프 값이 특정 한도를 초과하는 행 수를 나타냅니다. 내 목적은 이러한 외부 선의 비율을 계산하는 것입니다. 내가 이렇게 하면:

percentage=$(( multiplied / totalLines))

echo $percentage결과를 얻었습니다.

42

그러나 다음과 같이 부동 소수점 숫자의 백분율을 생성하고 싶습니다.

42.85

나는 이것을 달성하려고 노력합니다.

percentage=$( bc <<< 'scale=2; $multiplied / $totalLines' )

다음 오류로 인해 실패합니다.

(standard_in) 1: illegal character: $
(standard_in) 1: illegal character: $
(standard_in) 1: illegal character: L
(standard_in) 1: syntax error

부동 소수점 숫자의 백분율을 얻으려면 bc를 어떻게 올바르게 사용해야 합니까?

답변1

단순한

수행해야 할 작업이 (근사, 0으로 반올림) 수학뿐인 경우 다음을 사용하여 대부분의 쉘에서 직접 계산을 수행할 수 있습니다.

➤ printf '%8.2f\n' "$((multiplied*100/totalLines))e-2"
42.85

그리고 최신 버전의 bash, zsh 또는 ksh93에서는 다음과 같이 변수에 할당할 수 있습니다.

➤ printf -v percentage '%.2f\n' "$((multiplied*100/totalLines))e-2"
➤ echo "$percentage"
42.85

이는 정수 연산, 소수점 이하 두 자리, 공백 없이 0으로 반올림된 백분율입니다.

이는 쉘이 정수 수학을 수행하지만 항상 100을 곱한 값을 계산할 수 있기 때문입니다. $((…))결과적으로 정수는 4285가 됩니다 .

그러면 소수 구분 기호(점)를 왼쪽으로 두 자리 이동하기만 하면 됩니다.

그렇기 때문에 e-2그 가치는 그대로입니다 4285e-2.
그런 다음 결과는 소수점 이하 두 자리의 부동 소수점 숫자로 형식화됩니다 %8.2f.

이식성이 더 높은 옵션이지만 약간 느립니다(하위 쉘은 포크()를 의미함). 대부분의 쉘에서는 다음을 사용합니다.

percentage="$(printf '%8.2f\n' "$((outsideLines*100*100/totalLines))e-2")"

이 모든 작업은 쉘 내부에서 수행됩니다(printf가 내장된 경우).
외부 응용 프로그램을 로드할 필요가 없습니다. 이로 인해 속도가 빨라지고 CPU 부하가 줄어듭니다(예:하나숫자).

1000자까지 확장하려고 하지 마십시오. 쉘은 텍스트 파일 작업에 적합한 도구가 아닙니다.

최근의

백분율을 가장 가까운 짝수로 반올림해야 하는 경우. IEEE-754의 기본 반올림 방법에서는 소수 부분에 더 많은 자릿수를 사용해야 합니다. 다음과 같이 하면 더 많은 숫자(이 경우 13(소수점 11자리))를 얻을 수 있습니다.

$ printf '%.2f\n' "$((outsideLines*10**15/totalLines))e-13"
62.75

$ printf '%.4f\n' "$((outsideLines*10**15/totalLines))e-13"
62.7451

$ printf '%.6f\n' "$((outsideLines*10**15/totalLines))e-13"
62.745098

쉘의 정수 계산에서 소수점 이하 11자리 이상을 추출하는 것은 의미가 없습니다. 배정밀도 부동 소수점 숫자는 (일반적으로) 53비트로 제한되며 십진수는 16비트를 초과하지 않습니다. 백분율 숫자의 정수 부분에 사용되는 2자리 숫자를 빼면 소수점 이하 14자리 이하가 남습니다. 백분율이 작을수록 값이 감소하므로(수학은 정수 값으로 수행되므로) 소수점 이하 11자리 이하만 신뢰할 수 있습니다.

기원전

더 높은 정밀도(매우 작은 백분율)가 필요한 경우 쉘의 정수 수학을 사용하는 것은 의미가 없습니다. 이 경우에는 bc직접 사용하세요(외부 프로그램 로딩 및 실행 속도가 느려집니다).

$ bc <<<"scale=30; outsidelines=$outsideLines; totallines=$totalLines; outsidelines*100/totallines"

42.857142857142857142857142857142

$ val="$(bc <<<"scale=30; outsidelines=$outsideLines; totallines=$totalLines; outsidelines*100/totallines")"

$ printf '%.8f' "$val"
42.85714286

$ printf '%.6f' "$val"
42.857143

$ printf '%.4f' "$val"
42.8571

$ printf '%.2f' "$val"
42.86

1 쉘 정수 산술 라운드0이 되는 경향이 있다. 여기서는 제거 42.85714285714285...하기 위해 잘렸습니다 .42.850.00714285714285

² 운영 체제의 기본 반올림 모드에 따라 반올림합니다. 일반적으로 가장 가까운 값으로 짝수와 같습니다(은행가 반올림(그러나 일부 운영 체제에서는 0에 가장 가까운 관계일 수 있습니다.) 이는 소수점 11자리를 사용하여 수행됩니다. 예를 들어, 계산된 값이 두 자리에 가까울 경우 42.86이 값이 인쇄됩니다.

답변2

다음을 수행할 수 있습니다.

percentage=$(echo "scale=2; $multiplied / $totalLines" | bc)

답변3

감사해요 @스티븐 차제라스 나의 변수 오용을 지적해주세요


@user2323의 작업을 조금 마쳤습니다.답변:

> printf '%.2f\n' "$((outsideLines*100*100/totalLines))e-2"
> 42.85

끝에 "e-2"가 붙기 때문에 앞에 100을 더해주어야 합니다. "$((outsideLines*100/totalLines))"백분율의 정수 부분만 얻을 수 있습니다.

> printf '%.2f\n' "$((outsideLines*100/totalLines))"
> 42

, "$((outsideLines*100/totalLines))e-2"소수점 이하 두 자리의 부동 소수점 숫자를 얻지만 백분율은 얻지 않습니다.

> printf '%.2f\n' "$((outsideLines*100/totalLines))e-2"
> 0.42

관련 정보