これは自己回答のの質問です。質問をするのに合理的な調査は回答の部分にあります。私が回答を得るのに十分な調査をしていないと思われるので、反対票を投じないでください。ありがとう。いずれにせよ、このサイトにはbcのこの特性の説明(私が見つけることができる)はありません。
bc
を使用する場合、%
演算子は「剰余」を計算すると主張されており、はい、整数に対して機能し、スケールがゼロの場合:
$ bc <<<" scale=0; 27 % 7 " 6
ただし、スケールがゼロでない場合、「整数剰余」を与えることはできません。
$ bc <<<" scale=10; 27 % 7 " .0000000003
%
モジュロのこの定義が役立つ理由(または方法)
回答
%
演算子はで明確に定義されていますbc
マニュアル as [a] :
# 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) }
その長い定義はどのように役立ちますか?
-
整数の余り。
両方の関数と%
演算子の結果は、次のいくつかの演算と同等であることを証明します。数値が整数の場合、 scaleは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関数と同じではありません。以下で解決します。
-
10進数の残り。
数値n
がより長い10進数であり、スケールを変更すると、次のようになります。$ 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
そして、スケールが変更された場合e:
$ 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
上記のように、スケール値が変化して、、
d
、scale
。
I” 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 。
mod関数を深く掘り下げてみると、bc
で%
の実際の効果を明らかにする必要があります。 bcの%
演算子は、「切り捨て除算」を使用しています。0
に向かって丸められるもの。これは、n
および/または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
正しい間 math modは、常に正の余りを与える必要があります。
その(整数)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
[a]
expr%expr
式の結果は「剰余」であり、次のように計算されます。仕方。 a%bを計算するには、最初のa / bを計算して桁をスケーリングします。その結果を使用して、a-(a / b)* bをscale + scale(b)とscale(a)の最大値のスケールに計算します。
scaleがゼロに設定され、両方の式が整数の場合、この式は は整数残差関数です。
この脚注のポイントに続く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) };
この定義は数学の規則では完全に有効で正しいものですが、実際に適用しようとすると、言うだけでかなり混乱する可能性があります。