GNU BC:スケールが0以外の「モジュロ」(%)はどのように役立ちますか?

これは自己回答のの質問です。質問をするのに合理的な調査は回答の部分にあります。私が回答を得るのに十分な調査をしていないと思われるので、反対票を投じないでください。ありがとう。いずれにせよ、このサイトには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) } 

その長い定義はどのように役立ちますか?

  1. 整数の余り
    両方の関数と%演算子の結果は、次のいくつかの演算と同等であることを証明します。

    数値が整数の場合、 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関数と同じではありません。以下で解決します。

  1. 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 

    これは残りがその定義により、より用途が広くなります。

現在は、

です。

スケールの値。

  1. スケールの変更数値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 

    上記のように、スケール値が変化して、、dscale

I” internalmod%演算子を比較すると、どちらも同等であることが証明されていると想定します。

  1. 混乱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を使用する必要があります(実際に何をしているかを理解している場合を除く)。

  1. 数学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) }; 

この定義は数学の規則では完全に有効で正しいものですが、実際に適用しようとすると、言うだけでかなり混乱する可能性があります。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です