숫자를 기준으로 가로 세로 비율 높이를 계산하고 있습니다 x
. 이 예에서는 4:3 비율을 사용하고 너비는 800입니다. 결과(높이)는 600이어야 하지만 bash는 800을 반환하는데 그 이유를 모르겠습니다.
다른 언어를 사용해 보았지만 대부분 문제가 있는 것 같습니다. PHP는 작동하는 몇 안 되는 언어 중 하나인 것 같습니다.
PHP(600 반환)
php -r 'echo 800/(4/3);'
Python(800 반환)
python -c "print(800/(4/3))"
bc -l
약간 작동합니다 (600.00000000000000000150 반환)
-l
"표준 수학 라이브러리 정의"입니다. 그것이 무엇을 의미하는지 잘 모르겠지만 목표에 더 가까워지는 것 같습니다. 그런데 추가 0과 150은 어디에서 오는 것입니까?
echo '800 / (4 / 3)' | bc -l
나는 이것이 부동 소수점 처리 또는 잘림과 관련이 있다고 추측합니다 3/4
.
이제 를 사용할 수 있지만 php
, 비교적 간단한 계산에는 약간 과잉인 것 같습니다. 여기서 무슨 일이 일어나고 있는지 아시나요?
답변1
Bash 산술은 정수에만 적용됩니다. 따라서 4/3은 1을 반환합니다. 800/1은 800입니다.
입력을 제어할 수 있다면 나누기 전에 재구성하고 곱셈을 수행할 수 있습니다.
$ echo $(( 800*3/4 ))
600
다른 예도 "정수"입니다. 예를 들어, 4
교체를 통해 Python을 강제로 부동 상태로 만들면 4.0
다른 대답을 얻게 됩니다(Python 3에서는 이를 요구하지 않습니다).
$ python -c "print(800/(4.0/3))"
600.0
bc -l
표준 수학 라이브러리가 로드되지만( s()
사인, l()
자연 로그 등과 같은 함수 포함) 더 중요한 것은 scale
여기에서 20으로 설정된다는 것입니다. scale
나눗셈으로 밑수를 생성한 후 소수점 이하 자릿수가 몇 자리인지 정의하므로 (실제로는 )이 4/3
나오며 , 이것이 가 나오는 이유를 설명합니다 .1.33333333333333333333
133333333333333333333/1e+20
600.00000000000000000150
echo 'scale=1000; 800/(4/3)' | bc
(수학 라이브러리를 로드하지 않고) 더 높은 정밀도를 제공하지만 십진수로 표현할 수 없기 600
때문에 목표에 결코 도달하지 못할 것입니다.4/3
답변2
껍데기
일반적으로 말하면, 셸에서 일반 수학 연산을 수행하려면 외부 프로그램이 필요합니다.
$ bc -l <<<'800/(4/3)'
$ bc -l <<<'scale=200;800/(4/3)'
$ awk 'BEGIN{print 800/(4/3)}'
$ awk 'BEGIN{printf "%.60f\n",800/(4/3)}'
$ python3 -c 'print(800/(4/3))'
$ python3 -c 'print(format(800/(4/3),".60f"))'
왜
이는 두 가지 질문의 공동 결과입니다.
- 개별 작업이 정확합니다.
- 작업 순서.
개별 정확도
정수로 작동하는 경우 (4/3)
값은 입니다 1
.
Python에서도(Python 2는 /
"정수 나누기"를 의미함):
$ python2 -c 'print(4/3)'
1
하지만 Python3에서는 그렇지 않습니다.
$ python3 -c 'print(4/3)'
1.3333333333333333
그렇기 때문에 a 가 800/(4/3)
되고 800/1
원인이 됩니다 800
. (Python2에서)
$ python2 -c 'print(800/(4/3))'
800
$ python3 -c 'print(800/(4/3))'
600.0
Bash(대부분의 쉘과 마찬가지로)는 python2(정수)와 유사합니다.
$ bash -c 'echo (800/(4/3))'
800
주문하다
정수 변환 문제를 방지하기 위해 수학 순서를 변경할 수 있습니다.
$ python2 -c 'print(800*3/4)'
600
또는 Python에게 부동 소수점 숫자를 사용하도록 지시합니다.
$ python2 -c 'print(800/(float(4)/3))'
600.0
한계
하지만 이 숫자를 착각하지 마세요.정밀한. 확실히 다음과 같이 보일 수 있습니다:
python2 -c 'print(format(800/(4.0/3),".80f"))'
600.00000000000000000000000000000000000000000000000000000000000000000000000000000000
그리고 2^-50
(또는 55) 값은 이진수로 정확하게 표현될 수 있습니다.
$ python2 -c 'print(format(2**-50,".80f"))'
0.00000000000000088817841970012523233890533447265625000000000000000000000000000000
$ python2 -c 'print(format(2**-55,".80f"))'
0.00000000000000002775557561562891351059079170227050781250000000000000000000000000
그러나 정수와 부동 소수점을 혼합하면(또는 일반적으로 수치 계산을 수행하면) "범위를 벗어난" 결과를 얻게 됩니다.
$ python2 -c 'print(format(1 + 2**-50,".80f"))'
1.00000000000000088817841970012523233890533447265625000000000000000000000000000000
$ python2 -c 'print(format(1 + 2**-55,".80f"))'
1.00000000000000000000000000000000000000000000000000000000000000000000000000000000
일반적으로 이진수 53자리를 초과하는 숫자는 배정밀도 부동 소수점 숫자에서 잘립니다.