GNU BC: W jakim sensie „modulo” (%) ze skalą inną niż 0 jest przydatne?

To jest pytanie, na które odpowiedziano samodzielnie , badania, które warto zadać, znajdują się w części zawierającej odpowiedzi. Proszę nie głosować negatywnie, ponieważ uważasz, że nie przeprowadziłem wystarczających badań, aby uzyskać odpowiedź. Dzięki. W każdym razie nie ma opisu (jaki mogę znaleźć) tej cechy bc na tej stronie.

W przypadku używania bc, % ma obliczać „resztę” i tak, działa on dla liczb całkowitych i gdy skala wynosi zero :

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

Ale nie daje” reszty całkowitej „, jeśli skala jest różna od zera:

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

Dlaczego (lub w jaki sposób) ta definicja % modulo jest przydatna?

Odpowiedź

Operator % jest wyraźnie zdefiniowany w bc manual 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) } 

Zakładając, że max zostało zdefiniowane jako:

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

Do czego przydatna jest ta długa definicja?

  1. Reszta liczby całkowitej .
    I „ll pokaże oba internalmod i operator % wyniki, aby udowodnić, że są równoważne dla niektórych następnych operacji.

    Jeśli liczby są liczbami całkowitymi, i skala jest ustawiona na 0, jest to funkcja reszty całkowitej.

    $ 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 nie to samo, co funkcja modulacji matematycznej. Rozwiążę to poniżej.

  1. Reszta dziesiętna.
    Jeśli liczba n jest dłuższą liczbą dziesiętną i zmodyfikujemy skalę, otrzymamy:

    $ 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 

    Zauważ, że tutaj pierwsze 3 cyfry dziesiętne zostały usunięte, a reszta pochodzi z czwartej cyfry dziesiętnej.

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

    Oznacza to, że pozostała część jest bardziej wszechstronny dzięki tej definicji.

Teraz jest: reszta po wartość skali.

  1. Zmiana skali Zmiana skali jest wymagana, ponieważ liczba d (dzielnik) może mieć więcej cyfr dziesiętnych niż n. W takim przypadku potrzeba więcej miejsc po przecinku, aby uzyskać dokładniejszy wynik z dzielenia:

    $ 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 jeśli skala się zmieni 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 widać powyżej, wartość skali zmienia się, aby przedstawić dość dokładny wynik dzielenia dla dowolnej wartości n, d i scale.

I” Przyjmijmy, że przez porównanie między operatorem internalmod i % okazało się, że oba są równoważne.

  1. Zamieszanie . Uważaj, ponieważ używanie wartości d może być mylące:

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

    Oraz:

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

    To znaczy: wartość d (powyżej 1) będzie modyfikować efekt wartości zestawu skali.

Prawdopodobnie dla wartości d innych niż 1 powinieneś użyć scale = 0 (chyba że naprawdę wiesz, co robisz).

  1. Mod matematyczny .
    Ponieważ jesteśmy biorąc tak głęboki wgląd w funkcje modów, prawdopodobnie powinniśmy wyjaśnić rzeczywisty efekt % w bc. Operator % w bc używa „dzielenia obciętego”. Taką, która zaokrągla w kierunku 0. Jest to ważne w przypadku ujemnych wartości zarówno n, jak i / lub d:

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

    Znak reszty następuje po znaku dividend.

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

    Prawidłowe matematyka mod powinien dawać zawsze dodatnią resztę .

    Aby uzyskać tę (całkowitą) funkcję mod, użyj:

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

    I (wtedy) to zadziała:

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

[a]

wyrażenie% wyrażenie
Wynikiem wyrażenia jest „reszta” i jest obliczana w następujący sposób sposób. Aby obliczyć a% b, najpierw a / b jest obliczane do cyfr skali.Ten wynik jest używany do obliczenia a- (a / b) * b do skali maksimum skali + skala (b) i skali (a).
Jeśli skala jest ustawiona na zero, a oba wyrażenia są liczbami całkowitymi, to wyrażenie to funkcja reszty całkowitej.


Dla kodu bc, który następuje po punkcie, w którym ten przypis został wprowadzony do poprawnego działania, zdefiniuj alias jako:

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

I utwórz plik o nazwie $HOME/.func.bc, który zawiera ( przynajmniej):

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

Funkcję mod dla dowolnej liczby (całkowitej lub nie) można zdefiniować 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) }; 

Ta definicja jest całkowicie poprawna i poprawna dzięki regułom matematycznym, jednak może być dość myląca, gdy próbujesz ją zastosować w rzeczywistych przypadkach, mówiąc po prostu.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *