Detta är en självbesvarad fråga, den forskning som är rimlig att ställa en fråga finns i svaret, vänligen nedrösta inte eftersom du tror att jag inte har undersökt tillräckligt för ett svar. Tack. I vilket fall som helst finns det ingen beskrivning (som jag kan hitta) av denna egenskap hos bc på den här webbplatsen.
När du använder bc
, %
operatören påstås beräkna ”resten”, och ja, det fungerar för heltal och när -skalan är noll :
$ bc <<<" scale=0; 27 % 7 " 6
Men det går inte att ge” heltalsresten ”om skalan inte är noll:
$ bc <<<" scale=10; 27 % 7 " .0000000003
Varför (eller hur) är denna definition av %
modulo användbar?
Svar
%
-operatören är tydligt definierad i bc
manual som [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) }
Förutsatt att max
har definierats som:
define max(x,y){ if(x>y){return(x)};return(y) }
Hur är den långa definitionen användbar?
-
Resterande heltal .
I ”kommer att visa bådeinternalmod
-funktionen och%
-operatörens resultat för att bevisa att de är ekvivalenta för några av de nästa operationerna.Om siffrorna är heltal och skalan är inställd på 0, det är resten-funktionen.
$ 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
Det är inte samma sak som matematikmodfunktionen. Jag löser det nedan.
-
Återstående decimal.
Om siffrann
är ett längre decimaltal och vi ändrar skalan får vi:$ 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
Observera att här, de tre första decimalsiffrorna togs bort och resten som anges är från den fjärde decimalsiffran.
$ bc <<<"n=17.123456789;d=1; scale=7 ;a=internalmod(n,d,scale);b=n%d; print a," ",b,"\n"" .000000089 .000000089
Det visar att resten görs mer mångsidig med den definitionen.
Nu är det: resten efter skalans värde.
-
Skalförändring Ändring av skalan krävs eftersom siffran
d
(divisor) kan ha fler decimaler änn
. fler decimaler behövs för att få ett mer exakt resultat från uppdelningen:$ 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
Och om skalan ändras 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
Som kan ses ovan ändras skalvärdet för att ge ett rimligt exakt resultat av uppdelningen för vilket värde som helst av
n
,d
ochscale
.
I” Jag antar att både jämförelsen mellan internalmod
och %
operatören har visat sig vara ekvivalenta.
-
Förvirring . Var försiktig för att spela med värdet på
d
kan bli förvirrande:$ bc <<<"n=17.123456789; d=10; scale=3; a=n%d; print a," ",scale(a),"\n"" .003456789 9
Och:
$ bc <<<"n=17.123456789; d=1000; scale=3; a=n%d; print a," ",scale(a),"\n"" .123456789 9
Det vill säga: värdet på
d
(ovanför 1) kommer att ändra effekten av värdet på skalan.
För värden d
som är annorlunda än 1 bör du använda skalan = 0 (om du inte vet vad du gör).
-
Math mod .
Eftersom vi är tar vi ett sådant djupt dyk i modfunktioner, borde vi förmodligen klargöra den verkliga effekten av%
ibc
.%
-operatören i bc använder en ”trunkerande division”. En som avrundar mot0
. Det är viktigt för negativa värden för båden
och / ellerd
:$ bc <<<"scale=0; n=13; d=7; n%d; " 6 $ bc <<<"scale=0; n=13; d=-7; n%d; " 6
Resterande tecken följer tecknet på
dividend
.$ bc <<<"scale=0; n=-13; d=7; n%d; " -6 $ bc <<<"scale=0; n=-13; d=-7; n%d; " -6
Medan det är korrekt matematik mod ska ge en alltid positiv återstod .
För att få den (heltal) modfunktionen, använd:
# 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)) }
Och (då) fungerar det:
$ bc <<<"n=7.123456789; d=5; modeuclid(34.123456789,7)" 6.123456789
[a]
expr% expr
Resultatet av uttrycket är ”resten” och det beräknas i följande sätt. För att beräkna a% b beräknas först a / b för att skala siffror.Resultatet används för att beräkna a- (a / b) * b till skalan för skalan + skalan (b) och skalan (a).
Om skalan är noll och båda uttrycken är heltal är detta uttryck är funktionen för återstoden av heltal.
För bc
-koden som följer punkten där denna fotnot introducerades för att fungera korrekt, definiera ett alias som:
$ alias bc="bc -l "$HOME/.func.bc""
Och skapa en fil med namnet $HOME/.func.bc
som innehåller ( åtminstone):
# 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)) }
En modfunktion för valfritt tal (heltal eller inte) kan definieras som:
# 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) };
Denna definition är helt giltig och korrekt av matematiska regler, men det kan bli ganska förvirrande när man försöker tillämpa den i verkliga fall, bara säga.