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á?
-
Zbytek celých čísel .
Zobrazím jakinternalmod
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.
-
Desetinná část.
Pokud je číslon
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.
-
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
ascale
.
I“ Předpokládám, že porovnáním internalmod
a %
operátoru se ukázalo, že oba jsou rovnocenné.
-
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).
-
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%
vbc
. Operátor%
v bc používá „zkrácené dělení“. Jeden, který se zaokrouhluje na0
. To je důležité pro záporné hodnotyn
a / nebod
:$ 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.