このように長い定義が何の役に立つのですか?

このように長い定義が何の役に立つのですか?

これは自分に答えてください質問、質問をする合理的な研究は答えのセクションに含まれています。回答の調査が十分ではないと思うので、非推奨にしないでください。ありがとうございます。とにかく、このウェブサイトにbcのこの機能の説明はありません。

bcこの演算子は、使用時に「残り」を計算すると主張します%。はい、整数で動作します。スケールは0です:

$ bc <<<' scale=0; 27 % 7 '
6

ただし、小数点以下の桁数がゼロ以外の場合は、「整数の残り」を指定できません。

$ 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) }

このように長い定義が何の役に立つのですか?

  1. 整数の残り。関数と演算子の結果を
    表示することで、これらが次の作業と同じであることを示しています。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機能とは異なります。これについては以下で説明します。

  1. 少数の残り。
    数値が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
    

    そしてスケールが変わったら:

    $ 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

私は2つの演算子が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関数を探しているので、%inの実際の効果を明確にする必要がありますbc。 bc の演算子は%「切り捨て除算」を使用します。丸め方向0。これはnand / 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 を計算するために使用されます。
スケールがゼロに設定され、両方の式が整数の場合、式は整数の残りの関数です。


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の親セットです。

関連情報