Der %
Operator ist im bc
Handbuch eindeutig als [a] definiert :
# 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(y) }
Wie ist diese lange Definition nützlich?
1. Ganzzahliger Rest .
Ich werde sowohl die internalmod
Funktion als auch den %
Operator verwenden, um zu zeigen, dass sie für einige Operationen unten gleich sind
Wenn die Zahlen ganzzahlig sind und die Skalierung auf 0 gesetzt ist, handelt es sich um 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 das Gleiche wie die mathematische Mod-Funktion. Ich werde das unten lösen.
2. Dezimalrest.
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 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
Das zeigt, dass der Rest durch diese Definition vielseitiger wird.
3. Skalenwechsel Der Skalenwechsel ist erforderlich, da die Zahl d
(Divisor) mehr Dezimalstellen als haben kann n
. In diesem Fall sind mehr Dezimalstellen erforderlich, um ein genaueres Ergebnis 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:
$ 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, dehnt sich der Skalenwert eine einigermaßen genaue Ergebnis der Division für jeden Wert von präsentieren n
, d
und scale
.
Ich gehe davon aus, dass durch den Vergleich zwischen dem Operator internalmod
und dem %
Operator beide gleichwertig sind.
4. Verwirrung . Seien Sie vorsichtig, denn das Spiel mit dem Wert von d
kann verwirrend werden:
$ 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 Skalierungswerts.
Wahrscheinlich sollten Sie für d
andere Werte als 1 scale = 0 verwenden (sofern Sie nicht wirklich wissen, was Sie tun).
5. Math mod .
Da wir uns so intensiv mit Mod-Funktionen beschäftigen, sollten wir wahrscheinlich die tatsächliche Wirkung von %
in klären bc
. Der %
Operator in bc verwendet eine "abschneidende Division". Eine, die auf sich zukommt 0
. Das ist wichtig für negative Werte von beiden 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 Zeichen des Restes folgt dem Zeichen des dividend
.
$ bc <<<'scale=0; n=-13; d=7; n%d; ' -6 $ bc <<<'scale=0; n=-13; d=-7; n%d; ' -6
Während ein korrekter Mathe- Mod einen immer positiven Rest ergeben sollte .
Um diese (Ganzzahl-) 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 das wird funktionieren:
$ bc <<<"n=7.123456789; d=5; modeuclid(34.123456789,7)" 6.123456789
[ein]
expr% expr
Das Ergebnis des Ausdrucks ist der "Rest" und wird auf folgende Weise berechnet. Um a% b zu berechnen, wird zunächst a / b berechnet, um die 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 scale auf null gesetzt ist und beide Ausdrücke ganze Zahlen sind, ist dieser Ausdruck die ganzzahlige Restfunktion.
bc
Definieren Sie für den Code, der dem Punkt folgt, an dem diese Fußnote korrekt eingefügt wurde, einen Alias als:
$ alias bc='bc -l "$HOME/.func.bc"'
Und erstellen Sie eine Datei mit dem Namen $HOME/.func.bc
(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(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);if(x>0);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);scale=os;return(y) };
Diese Definition ist durch mathematische Regeln vollkommen gültig und richtig, kann jedoch recht verwirrend werden, wenn versucht wird, sie in realen Fällen anzuwenden.