GNU BC: Hvordan er “modulo” (%) med anden skala end 0 nyttig?

Dette er et selvbesvaret spørgsmål, den forskning, der er rimelig at bede om et spørgsmål, findes i svardelen, vær venlig ikke at nedstemme, fordi du mener, at jeg ikke har undersøgt nok til et svar. Tak. Under alle omstændigheder er der ingen beskrivelse (som jeg kan finde) af denne egenskab ved bc på dette websted.

Når du bruger bc, er % operatøren hævdes at beregne “resten”, og ja, det fungerer for heltal, og når -skalaen er nul :

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

Men det giver ikke” heltalets rest “, hvis skalaen ikke er nul:

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

Hvorfor (eller hvordan) er denne definition af % modulo nyttig?

Svar

% operatoren er tydeligt defineret 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) } 

Under forudsætning af max er defineret som:

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

Hvordan er den lange definition nyttig?

  1. Heltal resten .
    I “viser begge internalmod -funktionen og % -operatørresultaterne for at bevise, at de er ækvivalente for nogle af de næste operationer.

    Hvis tallene er heltal, og skala er indstillet til 0, det er funktionen for heltal resten.

    $ 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 matematikmodfunktionen. Jeg løser det nedenfor.

  1. Resterende decimal.
    Hvis tallet n er et længere decimaltal, og vi ændrer 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 

    Bemærk, at her blev de første 3 decimalcifre fjernet, og den givne rest er fra det fjerde decimaltal.

    $ 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 gøres mere alsidig af denne definition.

Nu er det: resten efter skalaens værdi.

  1. Skalaændring Skaleskift er påkrævet, fordi tallet d (divisor) kan have flere decimaler end n. flere decimaler er nødvendige for at få et mere præcist resultat fra divisionen:

    $ 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 ændres 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 ses ovenfor, ændres skalaværdien for at præsentere et rimeligt præcist resultat af divisionen for enhver værdi på n, d og scale.

I” Jeg antager, at begge sammenligninger mellem internalmod og % operatøren har vist sig at være ækvivalente.

  1. Forvirring . Vær forsigtig, fordi det at lege med værdien af d kan blive 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 sige: værdien af d (over 1) vil ændre effekten af værdien af skalasættet.

For værdier på d, der er forskellige fra 1, skal du sandsynligvis bruge scale = 0 (medmindre du virkelig ved, hvad du laver).

  1. Math mod .
    Da vi er tager vi et så dybt dyk i modfunktioner, bør vi sandsynligvis afklare den virkelige effekt af % i bc. % operatøren i bc bruger en “trunkerende division”. En der runder mod 0. Det er vigtigt for negative værdier for både n og / eller d:

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

    Restenes tegn 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 korrekt matematik mod skal give en altid positiv rest .

    For at få den (heltal) mod-funktion skal du bruge:

    # 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 (så) fungerer dette:

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

[a]

expr% expr
Resultatet af udtrykket er “resten”, og det beregnes i det følgende vej. For at beregne a% b beregnes først a / b til skaleringscifre.Resultatet bruges til at beregne a- (a / b) * b til skalaen for maksimum skala + skala (b) og skala (a).
Hvis skala er sat til nul, og begge udtryk er heltal, udtrykkes dette udtryk er funktionen til heltal resten.


For bc -koden, der følger det punkt, hvor denne fodnote blev introduceret til at fungere korrekt, definer et alias som:

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

Og opret en fil med navnet $HOME/.func.bc, der indeholder ( i det mindste):

# 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 til ethvert tal (heltal eller ej) 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 definition er fuldstændig gyldig og korrekt af matematiske regler, men den kan dog blive ret forvirrende, når man prøver at anvende den i virkelige tilfælde, bare ved at sige.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *