껍데기

껍데기

숫자를 기준으로 가로 세로 비율 높이를 계산하고 있습니다 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.33333333333333333333133333333333333333333/1e+20600.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자리를 초과하는 숫자는 배정밀도 부동 소수점 숫자에서 잘립니다.

관련 정보