GNU BC: Wie ist das „Modulo“ (%) mit einer anderen Skala als 0 nützlich?

Dies ist eine selbst beantwortete Frage, Die Forschung, die vernünftig ist, um eine Frage zu stellen, geht in den Antwortteil. Bitte stimmen Sie nicht ab, weil Sie glauben, dass ich nicht genug für eine Antwort recherchiert habe. Vielen Dank. Auf jeden Fall gibt es auf dieser Site keine Beschreibung (die ich finden kann) für dieses Merkmal von bc.

Bei Verwendung von bc wird die % soll den „Rest“ berechnen, und ja, er funktioniert für Ganzzahlen und wenn die Skala Null ist :

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

Der“ ganzzahlige Rest „wird jedoch nicht angegeben, wenn die Skala nicht Null ist:

$ bc <<<" scale=10; 27 % 7 " .0000000003 

Warum (oder wie) ist diese Definition des Moduls % nützlich?

Antwort

Der Operator % ist eindeutig definiert in bc Handbuch als [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) } 

Angenommen, max wurde definiert als:

define max(x,y){ if(x>y){return(x)};return(y) } 

Wie ist diese lange Definition nützlich?

  1. Ganzzahliger Rest .
    Ich werde beide und der Operator % beweisen, dass sie für einige der nächsten Operationen äquivalent sind.

    Wenn die Zahlen ganzzahlig sind, und Die Skalierung wird auf 0 gesetzt. Dies ist die ganzzahlige Restfunktion.

    $ 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 

Das ist nicht dasselbe wie die mathematische Mod-Funktion. Ich werde das unten lösen.

  1. Dezimaler Rest.
    Wenn die Zahl n eine längere Dezimalzahl ist und wir die Skala ändern, erhalten wir:

    $ 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 

    Beachten Sie, dass hier die ersten 3 Dezimalstellen entfernt wurden und der angegebene Rest von der vierten Dezimalstelle stammt.

    $ bc <<<"n=17.123456789;d=1; scale=7 ;a=internalmod(n,d,scale);b=n%d; print a," ",b,"\n"" .000000089 .000000089 

    Dies zeigt, dass der Rest wird durch diese Definition vielseitiger.

Jetzt ist es: der Rest nach der Wert der Skala.

  1. Skalenänderung Die Änderung der Skalierung ist erforderlich, da die Zahl d (Divisor) möglicherweise mehr Dezimalstellen als n enthält. In diesem Fall Weitere Dezimalstellen sind erforderlich, um ein genaueres Ergebnis aus der Division zu erhalten:

    $ 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 

    Und wenn sich die Skala ändert 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 

    Wie oben zu sehen ist, ändert sich der Skalierungswert, um ein einigermaßen genaues Ergebnis der Division für jeden Wert von , d und scale.

I“ Ich gehe davon aus, dass sich durch den Vergleich zwischen dem Operator internalmod und dem Operator % beide als äquivalent erwiesen haben.

  1. Verwirrung . Seien Sie vorsichtig, da das Spielen mit dem Wert von d verwirrend sein kann:

    $ bc <<<"n=17.123456789; d=10; scale=3; a=n%d; print a," ",scale(a),"\n"" .003456789 9 

    Und:

    $ bc <<<"n=17.123456789; d=1000; scale=3; a=n%d; print a," ",scale(a),"\n"" .123456789 9 

    Das heißt: Der Wert von d (über 1) ändert den Effekt des Werts des Skalensatzes.

Wahrscheinlich sollten Sie für Werte von d, die sich von 1 unterscheiden, scale = 0 verwenden (es sei denn, Sie wissen wirklich, was Sie tun).

  1. Math mod .
    Da sind wir Wenn wir uns so intensiv mit Mod-Funktionen befassen, sollten wir wahrscheinlich den tatsächlichen Effekt von % in bc klären. Der Operator % in bc verwendet eine „abschneidende Division“. Eine, die in Richtung 0 rundet. Dies ist wichtig für negative Werte von n und / oder d:

    $ bc <<<"scale=0; n=13; d=7; n%d; " 6 $ bc <<<"scale=0; n=13; d=-7; n%d; " 6 

    Das Vorzeichen des Restes folgt dem Vorzeichen der dividend.

    $ bc <<<"scale=0; n=-13; d=7; n%d; " -6 $ bc <<<"scale=0; n=-13; d=-7; n%d; " -6 

    Während eine korrekte math mod sollte einen immer positiven Rest geben .

    Um diese (ganzzahlige) Mod-Funktion zu erhalten, verwenden Sie:

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

    Und (dann) funktioniert dies:

    $ bc <<<"n=7.123456789; d=5; modeuclid(34.123456789,7)" 6.123456789 

[a]

Ausdruck% Ausdruck
Das Ergebnis des Ausdrucks ist der „Rest“ und wird im Folgenden berechnet Weg. Um a% b zu berechnen, wird zuerst a / b berechnet, um Ziffern zu skalieren.Dieses Ergebnis wird verwendet, um a- (a / b) * b auf die Skala des Maximums von Skala + Skala (b) und Skala (a) zu berechnen.
Wenn die Skala auf Null gesetzt ist und beide Ausdrücke ganze Zahlen sind, ist dieser Ausdruck ist die ganzzahlige Restfunktion.


Für den Code bc, der auf den Punkt folgt, an dem diese Fußnote steht wurde eingeführt, um korrekt zu funktionieren. Definieren Sie einen Alias als:

$ alias bc="bc -l "$HOME/.func.bc"" 

und erstellen Sie eine Datei mit dem Namen $HOME/.func.bc, die ( mindestens):

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

Eine Mod-Funktion für eine beliebige Zahl (Ganzzahl oder nicht) kann definiert werden als:

# 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) }; 

Diese Definition ist nach mathematischen Regeln vollkommen gültig und korrekt. Sie kann jedoch ziemlich verwirrend werden, wenn Sie versuchen, sie in realen Fällen anzuwenden, indem Sie nur sagen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.