이 숫자가 105000000이라고 가정해 보겠습니다. 이 형식에서는 숫자가 얼마나 큰지 쉽게 알 수 없으므로 printf
메시지가 표시되면 "과학적" 표기법을 사용하려고 합니다.
% printf "%.3E" 105000000
1.050E+08
이것이 더 좋지만 출력이 10의 300 만, 10억, 1조 등 의 제곱 형식인 "엔지니어링" 표기법을 사용하고 싶습니다.
예를 들어 다음과 같이 형식을 지정하고 싶습니다.
105000 => 105.0E+03 (105 thousand)
105000000 => 105.0E+06 (105 million)
105000000000 => 105.0E+09 (105 billion)
...
이것이 가능합니까 printf
?
답변1
printf
나는 이것을 할 수 있는 구현 을 모른다 . printf '%E\n' 123
부동 소수점 형식에 대한 지원은 선택 사항이므로 POSIX가 완벽하게 작동한다고 보장할 수도 없습니다 .
다양한 구현을 통해 다음 형식으로 로케일에서 천 단위 구분 기호를 출력 printf
할 수 있습니다 .%'f
$ LC_NUMERIC=en_GB.UTF-8 printf "%'.0f\n" 105000000
105,000,000
$ LC_NUMERIC=fr_FR.UTF-8 printf "%'.0f\n" 105000000
105 000 000
$ LC_NUMERIC=da_DK.UTF-8 printf "%'.0f\n" 105000000
105.000.000
$ LC_NUMERIC=de_CH.UTF-8 printf "%'.0f\n" 105000000
105'000'000
$ LC_NUMERIC=ps_AF.UTF-8 printf "%'.0f\n" 105000000
105٬000٬000
printf
내장된 를 사용하면 K/M/G... 접미사 및 Ki/Mi/Gi 접미사 ksh93
도 사용할 수 있습니다 .%#d
%#i
$ printf '%#d\n' 105000000 $((2**22))
105M
4.2M
$ printf '%#i\n' 105000000 $((2**22))
100Mi
4.0Mi
(그러나 정밀도는 변경할 수 없습니다. 예를 들어 Ki
에서 로의 전환은 Mi
1024 Ki 대신 1000 Ki입니다. ls -lh
이는 GNU 형식(예: GNU )에 익숙하다면 놀랄 수도 있습니다. 또한 다음으로 제한됩니다.정수그 수는 2 63 -1 (8Ei - 1)) 만큼 높습니다 .
수동으로 구현하는 방법은 다음을 사용하십시오 zsh
.
eng() {
local n="${(j: :)argv}" exp
zmodload zsh/mathfunc
if ((n)) && ((exp = int(floor(log10(abs(n)) / 3)) * 3)); then
printf '%.10ge%d\n' "n / 1e$exp" exp
else
printf '%.10g\n' "$n"
fi
}
그런 다음:
$ eng 123
123
$ eng 12345
12.345e3
$ eng 0.000000123123
123.123e-9
$ eng 1. / -1234
-810.3727715e-6
다른 많은 언어 와 마찬가지로 zsh
부동 소수점 숫자와 관련된 연산은 부동 소수점 연산(프로세서 double
유형 사용)으로 수행되는 반면, 정수만 관련된 연산은 정수 연산(프로세서 유형 사용) 장치 유형으로 수행됩니다 long
. 이는 다음과 같은 몇 가지 효과를 갖습니다.
$ eng 1 / -1234
0
$ eng 1. / -1234
-810.3727715e-6
뿐만 아니라:
$ eng 1 \*{2..28}. # factorial 28
304.8883446e27
$ eng 1 \*{2..28}
-5.968160533e18 # 64bit signed integer overflow
eng
(이 기능 에만 국한된 것은 아니지만 )
또는 POSIX 를 사용하는 POSIX 쉘 함수로 bc
임의의 정밀도를 허용합니다.
eng() (
IFS=" "
scale=$1; shift
bc -l << EOF |
s = scale = $scale
if (scale < 20) s = 20
n = $*
if (n != 0) {
scale = s
a = n; if (a < 0) a = -a
e = l(a) / l(10) / 3 + 10 ^ -15
if (e < 0) e -= 1
scale = 0
e = e / 1 * 3
scale = s
if (scale <= -e) scale = 1 - e
n = n / 10^e
scale = $scale
}
n/1
if (e != 0) e
EOF
sed '
:1
/\\$/{
N;b1
}
s/\\\n//g
/\./s/0*$//
s/\.$//
$!N
s/\n/e/'
)
(n 값(예: 0.001)에 대한 지수 log10(n)을 계산할 때 반올림 오류를 오프셋하기 위해 1e-15만큼 오프셋합니다.)
여기서 첫 번째 매개변수는 다음과 같이 처리됩니다.규모:
$ eng 2 1/3
330e-3
$ eng 20 1/3
333.33333333333333333e-3
기본적으로 엔지니어링 표기법을 이해하지 못 하므로 bc
다음과 같이 작성해야 합니다.
$ eng 20 "1.123123 * 10^2000"
112.3123e1998