GNU BC: Jak je užitečné „modulo“ (%) s měřítkem jiným než 0?

Toto je samostatně zodpovězená otázka, výzkum, který je rozumné položit si otázku, jde do části odpovědí, prosím, nehlasujte, protože si myslíte, že jsem dostatečně nezkoumal odpověď. Dík. V každém případě na této stránce není žádný popis (který najdu) této charakteristiky BC.

Při použití bc se vypočítává „zbytek“ a ano, funguje to pro celá čísla a když je měřítko nula :

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

Neposkytne však“ celé číslo „, pokud stupnice není nula:

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

Proč (nebo jak) je tato definice modulu % užitečná?

Odpověď

Operátor % je jasně definován v bc manuální jako [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) } 

Za předpokladu, že max byl definován jako:

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

Jak je ta dlouhá definice užitečná?

  1. Zbytek celých čísel .
    Zobrazím jak internalmod funkce a % výsledky operátoru dokazují, že jsou ekvivalentní pro některé z dalších operací.

    Pokud jsou čísla celá čísla a scale is set to 0, it is the integer remainder function.

    $ 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 

To není totéž jako funkce matematického módu. To níže vyřeším.

  1. Desetinná část.
    Pokud je číslo n delší desetinné číslo a měřítko upravíme, dostaneme:

    $ 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 

    Všimněte si, že zde byly odstraněny první 3 desetinná místa a zbytek je ze čtvrté desetinné číslice.

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

    To ukazuje, že zbytek je touto definicí univerzálnější.

Nyní je: zbytek po hodnota měřítka.

  1. Změna měřítka Změna měřítka je nutná, protože číslo d (dělitel) může mít více desetinných číslic než n. V takovém případě k přesnějšímu výsledku dělení je zapotřebí více desetinných míst:

    $ 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 

    A pokud se změna měřítka změní 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 

    Jak je vidět výše, hodnota měřítka se změní tak, aby představovala přiměřeně přesný výsledek dělení pro jakoukoli hodnotu n, d a scale.

I“ Předpokládám, že porovnáním internalmod a % operátoru se ukázalo, že oba jsou rovnocenné.

  1. Zmatek . Buďte opatrní, protože hraní s hodnotou d může být matoucí:

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

    A:

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

    To znamená: hodnota d (nad 1) změní účinek hodnoty škálované sady.

Pravděpodobně pro hodnoty d jiné než 1 byste měli použít scale = 0 (pokud opravdu nevíte, co děláte).

  1. Matematický režim .
    Protože jsme při takovém hlubokém ponoření do funkcí modů bychom pravděpodobně měli vyjasnit skutečný účinek % v bc. Operátor % v bc používá „zkrácené dělení“. Jeden, který se zaokrouhluje na 0. To je důležité pro záporné hodnoty n a / nebo d:

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

    Znak zbytku následuje za znakem dividend.

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

    Zatímco správný matematika mod by měla dát vždy pozitivní zbytek .

    Chcete-li získat tuto (celočíselnou) funkci mod, použijte:

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

    A (pak) to bude fungovat:

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

[a]

expr% expr
Výsledkem výrazu je „zbytek“ a je vypočítán v následujícím cesta. Chcete-li vypočítat% b, nejprve se vypočítá a / b na měřítko číslic.Tento výsledek se používá k výpočtu a- (a / b) * b na měřítko maxima scale + scale (b) a scale (a).
Pokud je scale nastaven na nulu a oba výrazy jsou celá čísla, tento výraz je funkce zbytku celého čísla.


Pro kód bc, který následuje za bodem, kde je tato poznámka pod čarou byl zaveden, aby fungoval správně, definujte alias jako:

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

A vytvořte soubor s názvem $HOME/.func.bc, který obsahuje ( alespoň):

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

Funkci mod pro libovolné číslo (celé číslo nebo ne) lze definovat jako:

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

Tato definice je podle matematických pravidel naprosto platná a správná, může se však stát docela matoucí, pokud se ji pokusíte použít ve skutečných případech, stačí říct.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *