Dette er et selvsvaret spørsmål, forskningen som er rimelig å be om et spørsmål, går inn i svardelen, vær så snill å ikke nedstemme fordi du mener at jeg ikke har undersøkt nok for et svar. Takk. I alle fall er det ingen beskrivelse (som jeg kan finne) av denne egenskapen til bc på dette nettstedet.
Når du bruker bc
, %
operatøren hevdes å beregne «resten», og ja, det fungerer for heltall og når skalaen er null :
$ bc <<<" scale=0; 27 % 7 " 6
Men det gir ikke» heltallet resten «hvis skalaen ikke er null:
$ bc <<<" scale=10; 27 % 7 " .0000000003
Hvorfor (eller hvordan) er denne definisjonen av %
modulo nyttig?
Svar
%
operatoren er tydelig definert 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) }
Forutsatt at max
er definert som:
define max(x,y){ if(x>y){return(x)};return(y) }
Hvordan er den lange definisjonen nyttig?
-
Heltall resten .
I «vil vise bådeinternalmod
-funksjonen og%
-operatørresultatene viser at de er ekvivalente for noen av de neste operasjonene.Hvis tallene er heltall, og skala er satt til 0, det er funksjonen for resten av hele tallet.
$ 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 er ikke det samme som matte mod-funksjonen. Jeg løser det nedenfor.
-
Desimal rest.
Hvis talletn
er et lengre desimaltall, og vi endrer skalaen, 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
Merk at her ble de tre første desimaltegnene fjernet, og resten som er gitt er fra det fjerde desimaltallet.
$ bc <<<"n=17.123456789;d=1; scale=7 ;a=internalmod(n,d,scale);b=n%d; print a," ",b,"\n"" .000000089 .000000089
Det viser at resten blir gjort mer allsidig av den definisjonen.
Nå er det: resten etter verdien på skalaen.
-
Skalaendring Skalaendring er nødvendig fordi tallet
d
(divisor) kan ha flere desimaltegn ennn
. flere desimaler er nødvendig for å få et mer presist resultat fra divisjonen:$ 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
Og hvis skalaen endres 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 det kan sees ovenfor, endres skalaverdien for å presentere et rimelig presist resultat av delingen for en hvilken som helst verdi på
n
,d
ogscale
.
I» Jeg antar at ved sammenligningen mellom internalmod
og %
operatøren begge har vist seg å være ekvivalente.
-
Forvirring . Vær forsiktig fordi det å spille med verdien
d
kan bli forvirrende:$ bc <<<"n=17.123456789; d=10; scale=3; a=n%d; print a," ",scale(a),"\n"" .003456789 9
Og:
$ bc <<<"n=17.123456789; d=1000; scale=3; a=n%d; print a," ",scale(a),"\n"" .123456789 9
Det vil si: verdien til
d
(over 1) vil endre effekten av verdien av skalasettet.
Sannsynligvis, for verdier på d
som er forskjellige enn 1, bør du bruke skala = 0 (med mindre du virkelig vet hva du gjør).
-
Math mod .
Siden vi er tar vi et så dypt dykk inn i mod-funksjoner, bør vi sannsynligvis avklare den virkelige effekten av%
ibc
.%
operatøren i bc bruker en «avkuttende divisjon». En som runder mot0
. Det er viktig for negative verdier av båden
og / ellerd
:$ bc <<<"scale=0; n=13; d=7; n%d; " 6 $ bc <<<"scale=0; n=13; d=-7; n%d; " 6
Tegn for resten følger tegnet på
dividend
.$ bc <<<"scale=0; n=-13; d=7; n%d; " -6 $ bc <<<"scale=0; n=-13; d=-7; n%d; " -6
Mens det er riktig matematikk mod skal gi en alltid positiv rest .
For å få den (heltall) mod-funksjonen, bruk:
# 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)) }
Og (da) vil dette fungere:
$ bc <<<"n=7.123456789; d=5; modeuclid(34.123456789,7)" 6.123456789
[a]
expr% expr
Resultatet av uttrykket er «resten» og det beregnes i det følgende vei. For å beregne a% b beregnes først a / b for å skalere sifre.Resultatet blir brukt til å beregne a- (a / b) * b til skalaen for maksimal skala + skala (b) og skala (a).
Hvis skala er satt til null og begge uttrykkene er heltall, vil dette uttrykket er resten av funksjonen.
For bc
-koden som følger punktet der denne fotnoten er ble introdusert for å fungere riktig, definer et alias som:
$ alias bc="bc -l "$HOME/.func.bc""
Og opprett en fil med navnet $HOME/.func.bc
som inneholder ( i det minste):
# 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 mod-funksjon for et hvilket som helst tall (heltall eller ikke) kan defineres 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) };
Denne definisjonen er helt gyldig og korrekt av matteregler, men den kan bli ganske forvirrende når du prøver å bruke den i virkelige tilfeller, bare å si.