![이렇게 긴 정의가 무슨 소용이 있나요?](https://linux55.com/image/141256/%EC%9D%B4%EB%A0%87%EA%B2%8C%20%EA%B8%B4%20%EC%A0%95%EC%9D%98%EA%B0%80%20%EB%AC%B4%EC%8A%A8%20%EC%86%8C%EC%9A%A9%EC%9D%B4%20%EC%9E%88%EB%82%98%EC%9A%94%3F.png)
이것은스스로에게 답해보세요질문, 질문을 하는 합리적인 연구는 답변 섹션에 담겨 있습니다. 답변에 대한 조사가 충분하지 않다고 생각하므로 비추천하지 마십시오. 감사해요. 어쨌든, 이 웹사이트에는 bc의 이 기능에 대한 설명이 없습니다.
bc
이 연산자는 사용될 때 "나머지"를 계산한다고 주장합니다 %
. 예, 정수와 함께 작동합니다.규모가 0이다:
$ bc <<<' scale=0; 27 % 7 '
6
그러나 소수 자릿수가 0이 아닌 경우 "정수 나머지"를 제공할 수 없습니다.
$ bc <<<' scale=10; 27 % 7 '
.0000000003
이 모듈 정의가 왜(또는 어떻게) %
유용한가요?
답변1
운영자님이 %
아주 명확하게 말씀해주셨네요bc
매뉴얼에 정의된~처럼[ㅏ]:
# Internal % operator definition:
define internalmod(n,d,s) { auto r,oldscale;
oldscale=scale; r=n/d;
s=max(s+scale(d),scale(n));
scale=s; r = n-(r)*d;
scale=oldscale; return(r) }
max
다음과 같이 정의되었다고 가정합니다 .
define max(x,y){ if(x>y){return(x)};return(y) }
이렇게 긴 정의가 무슨 소용이 있나요?
정수 나머지. 함수와 연산자 결과를
보여줌으로써 이들이 다음에 나오는 일부 작업과 동일하다는 것을 보여 드리겠습니다.internalmod
%
숫자가 정수이고 스케일이 0으로 설정된 경우 이는 정수 나머지 함수입니다.
$ bc <<<'n=17; d=3; scale=0;a=internalmod(n,d,scale);b=n%d;print a," ",b,"\n"' 2 2 $ bc <<<'n=17; d=6; scale=0;a=internalmod(n,d,scale);b=n%d;print a," ",b,"\n"' 5 5
이는 수학 mod 기능과 다릅니다. 이에 대해서는 아래에서 다루겠습니다.
소수 나머지.
숫자가n
더 긴 십진수이고 스케일을 수정하면 다음과 같은 결과를 얻습니다.$ bc <<<'n=17.123456789;d=1; scale=0 ;a=internalmod(n,d,scale);b=n%d; print a," ",b,"\n"' .123456789 .123456789 $ bc <<<'n=17.123456789;d=1; scale=3 ;a=internalmod(n,d,scale);b=n%d; print a," ",b,"\n"' .000456789 .000456789
여기서는 소수점 이하 3자리가 제거되고 나머지는 소수점 4자리부터 나옵니다.
$ bc <<<'n=17.123456789;d=1; scale=7 ;a=internalmod(n,d,scale);b=n%d; print a," ",b,"\n"' .000000089 .000000089
이는 이 정의에 따라 나머지가 더욱 일반화됨을 보여줍니다.
지금은: 나머지뒤쪽에규모의 가치.
규모 변화 숫자
d
(제수)의 소수 자릿수가 .보다 많을 수 있으므로 소수 자릿수를 변경해야 합니다n
. 이 경우 더 정확한 나누기 결과를 얻으려면 더 많은 소수가 필요합니다.$ bc <<<'n=17.123456789; d=1.00000000001; scale=0; a=internalmod(n,d,scale); b=n%d; print a," ",scale(a)," -- ", b," ",scale(b),"\n"' .12345678883 11 -- .12345678883 11
그리고 규모가 변경되면:
$ bc <<<'n=17.123456789; d=1.00000000001; scale=5; a=internalmod(n,d,scale); b=n%d; print a," ",scale(a)," -- ", b," ",scale(b),"\n"' .0000067888287655 16 -- .0000067888287655 16
n
위에서 볼 수 있듯이,d
, 및 의 모든 값에 대해 스케일 값이 변경되어 상당히 정확한 나눗셈 결과를 렌더링합니다scale
.
나는 두 연산자가 internalmod
와 연산자를 %
비교하여 동등한 것으로 입증되었다고 가정합니다.
어찌할 바를 모르는. 사용된 값이
d
혼동될 수 있으므로 주의하세요.$ bc <<<'n=17.123456789; d=10; scale=3; a=n%d; print a," ",scale(a),"\n"' .003456789 9
그리고:
$ bc <<<'n=17.123456789; d=1000; scale=3; a=n%d; print a," ",scale(a),"\n"' .123456789 9
즉,
d
위의 (1의 값)은 비율 설정 값의 효과를 수정합니다.
d
어쩌면 1이 아닌 값의 경우 scale=0을 사용해야 할 수도 있습니다(무엇을 하고 있는지 실제로 알지 않는 한).
수학적 모델.
우리는 mod 함수를 탐구하고 있으므로%
in 의 실제 효과를 명확히 해야 할 것입니다bc
. bc의 연산자는%
"잘린 나눗셈"을 사용합니다. 반올림 방향0
. 이는n
and/or의 음수 값에 중요합니다d
.$ bc <<<'scale=0; n=13; d=7; n%d; ' 6 $ bc <<<'scale=0; n=13; d=-7; n%d; ' 6
나머지의 부호는 의 부호 뒤에 옵니다
dividend
.$ bc <<<'scale=0; n=-13; d=7; n%d; ' -6 $ bc <<<'scale=0; n=-13; d=-7; n%d; ' -6
비록 정확하지만수학모듈은 다음을 제공해야 합니다.나머지는 항상 긍정적이다.
(정수) mod 함수를 얻으려면 다음을 사용하십시오.
# Module with an always positive remainder (euclid division). define modeuclid(x,div) { if(div!=int(div)){ "error: divisor should be an integer ";return(0)}; return(x - div*int(x/div)) }
그러면 (그러면) 이것이 작동할 것입니다:
$ bc <<<"n=7.123456789; d=5; modeuclid(34.123456789,7)" 6.123456789
[ㅏ]
expr %
expr 표현식의 결과는 "나머지"이며 다음과 같이 계산됩니다. a%b를 계산하려면 먼저 a/b를 계산하여 숫자의 크기를 조정하세요. 이 결과는 scale+scale(b)와 scale(a)의 최대 비율로 a-(a/b)*b를 계산하는 데 사용됩니다.
척도가 0으로 설정되고 두 표현식이 모두 정수인 경우 표현식은 정수 나머지 함수입니다.
bc
이 각주가 소개된 지점 뒤의 코드가 작동 하려면 별칭을 다음과 같이 정의하세요.
$ alias bc='bc -l "$HOME/.func.bc"'
$HOME/.func.bc
(적어도) 다음과 같은 이름의 파일을 만듭니다 .
# Internal % operator definition:
define internalmod(n,d,s) { auto r,oldscale;
oldscale=scale; r=n/d;
s=max(s+scale(d),scale(n));
scale=s; r = n-(r)*d;
scale=oldscale; return(r) }
# Max function
define max(x,y){ if(x>y){return(x)};return(y) }
# Integer part of a number toward 0: -1.99 -> -1, 0.99 -> 0
define int(x) { auto os;os=scale;scale=0;
x=sgn(x)*abs(x)/1;scale=os;return(x) }
define sgn (x) { if (x<0){x=-1};if(x>0){x=1};return(x) };
define abs (x) { if (x<0) x=-x; return x };
# Module with an always positive remainder (euclid division).
define modeuclid(x,div) { if(div!=int(div)){
"error: divisor should be an integer ";return(0)};
return(x - div*int(x/div)) }
모든 숫자(정수 또는 비정수)에 대한 mod 함수는 다음과 같이 정의할 수 있습니다.
# Module with an always positive remainder (euclid division).
define modeuclid(x,div) { div=abs(div);return(x - div*floor(x/div)) }
# Round down to integer below x (toward -inf).
define floor (x) { auto os,y;os=scale;scale=0;
y=x/1;if(y>x){y-=1};scale=os;return(y) };
수학의 규칙에 따르면 이 정의는 완벽하게 타당하고 정확하지만, 이를 실제 상황에 적용하려고 하면 상당히 혼란스러울 수 있습니다.
답변2
BC와 해당 연산자에 대한 설명은 POSIX 표준의 일부입니다. 현재 위치는 다음과 같습니다.
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html
a % b는 a - (a / b) * b로 정의되고 max(scale + scale(b), scale(a))로 계산됩니다.
현재 버전 1.07.1 기준으로 GNU BC의 경우입니다. BSD의 경우 BC는 단지 DC의 껍질일 뿐이고, DC는 "%"를 나타내기 위해 "bn"을 사용합니다.
C-BC에서도 마찬가지이다. C-BC, 그 출처는 여기에 보관되어 있습니다:
https://github.com/RockBrentwood/CBC
BC의 대규모 확장이며 C에 더 가깝고 (주로) GNU BC 및 BSD BC의 상위 집합입니다.