La radice quadrata

Sk_Anonymous
Calcolare la radice di un numero intero facendo
uso dela sola operazione di sottrazione.
karl.

Risposte
fireball1
Io sapevo che si può fare scomponendo il numero in fattori primi,
ma con la sola operazione di sottrazione... Non saprei proprio...

Sk_Anonymous
Pensa alla somma dei primi n dispari....
karl.

Nidhogg
program quadrati;
uses wincrt;
Var i,s,n,k:integer;
begin
   write('Inserisci il numero: ');
   readln(n);
   i:=1;
   s:=0;
   k:=1;
   while s<n do
      begin
         s:=s+i;
         if s=n then writeln('Radice quadrata: ',k)
            else 
               begin
                  i:=2*k+1;
                  inc(k);
               end;
      end;
      if s>n then writeln('Radice quadrata approssimata: ',k-2);
end.

Sk_Anonymous
L'operazione da fare e' riferita a
tutti i numeri interi e non solamente ai
quadrati perfetti.
Per esempio sqrt(123) si puo'
ottenere facendo le sottrazioni.....
karl.

Nidhogg
Scusami karl ma si calcola, per quadrati non perfetti, la radice quadrata approssimata. Se si anche con numeri decimali?

Ciao, Ermanno.

Sk_Anonymous
Il calcolo si basa sulla proprietà che il quadrato di
un numero n è pari alla somma dei primi n numeri dispari.
Per esempio:4^2=1+3+5+7
L'algoritmo per il calcolo della radice quadrata consiste
quindi nel sottrarre al numero di partenza una sequenza di numeri dispari crescenti, fino a che il risultato non diventa negativo.
Il numero di iterazioni richieste sarà pari alla valore
della radice quadrata di tale numero.
Ovviamente tale valore sara' esatto od approssimato
a meno di una unita' a seconda che n sia quadrato
perfetto oppure no.
karl.

tony19
scusa, karl, pongo ora due domande che (già immaginando la tua soluzione) non avevo fatto per non rompere le uova nel paniere ad altri solutori
quote:
... Il numero di iterazioni richieste sarà pari alla valore
della radice quadrata di tale numero. [karl]


1): il contare le iterazioni è un'operazione di addizione (che quindi invaliderebbe il tipo di soluzione) o no?
ovvio escamotage sarebbe il contare sottraendo (da n), e alla fine sottrarre ancora il risultato (sempre da n)!
2): il successivo numero dispari lo ottengo per sottrazione di -2?

Sk_Anonymous
Faccio un esempio.
sqrt(123)=?
Allora :
123-1=122
122-3=119
119-5=114
114-7=107
107-9=98
98-11=87
87-13=74
74-15=59
59-17=62
62-19=43
43-21=22
22-23=-1 Stop.
Le iterazioni prima di arrivare a -1 sono 11
e questa e' la radice (a meno di un'unita') di 123.
Il conto delle iterazioni non lo considererei
come calcolo effettivo perche' non incide numericamente
sui vari passaggi (almeno cosi' credo).
Ovviamente il procedimento e' improponibile
sul piano pratico (cosa accadrebbe se il numero fosse
123456?)e puo' interessare solo da un punto di vista
concettuale in quanto e' basato sul fatto che
la somma di interi dispari consecutivi,a partire
da 1,e'notoriamente un quadrato esatto.
Saluti da karl.

JvloIvk
Carino il metodo,peccato che fornisca solo un valore approssimato.Esiste un altro metodo,scoperto da Newton,che fornisce la radice di un numero con le 4 operazioni fondamentali:
Dato un numero n formato da m cifre prendiamo in considerazione un numero a ,formato da m/2 cifre(in realtà questo numero può essere formato da un numero di cifre arbitrario,ma la scelta di m/2 serve a velocizzare l'algoritmo).
L'algoritmo è il seguente:
-Si divide n per a
-si somma a al risultato
-si dvide tutto per 2
Si ripete il procedimento,ma anzichè a si considera il risultato ottenuto precedentemente(n/a+a)/2
Esempio:calcora sqrt10
scegliamo un numero di 1 crifa :a=5
a(1)=7/2
a(2)=(2n/7+7/2)/2
e così via...

Altro metodo è lo sviluppo di McLaurin:

tony19
continuo il topicsul divertente problema della radice per sottrazioni e, visto che Leonardo aveva mandato un programma in Pascal, ne mando uno che (mi pare proprio) non contiene che sottrazioni.

l'ho provato sommariamente: funziona con 2 decimali e mezzo, e con radicandi anche non interi.
se lo fate girare e trovate dei bug, mi fate un piacere (io non conosco quasi per nulla il Pascal, e programmo con l'help aperto).
chissà che velocità (?) avete sulle vostre macchine.

contiene, tra l'altro, arcane costanti, la cui spiegazione è lasciata
come esercizio a qualche studente di informatica ...chi si fa sotto? (il capire il programma d'un altro è un lavoraccio che capita spesso nella vita)

program radice01;
{$N+}
uses wincrt;
const beg0 :extended =-1.490116119384765625e-8; n=8192;
var xin, x, newx, rad, disp, t: extended; ns: integer;
begin
  writeln('calcolo di sqrt col "metodo di karl"');
  repeat
    write('dammi un numero R (se è negativo, smetto) '); read(xin);
    if xin>=0 then
      begin
        x:=xin; disp:=beg0; rad:=0;
        while x>0 do
          begin
            disp:=disp-beg0-beg0;
            newx:=x-disp;
            if newx >= 0 then rad:=rad-beg0;
            {writeln('a','x=',x,' disp=',disp,'newx=',newx,' rad=',rad);}
            x:=newx;
          end;
        {writeln('b', 'x=',x,' disp=',disp, ' rad=', rad);}
        (* and now ... *)
        t:=0; ns:= n;
        repeat
          ns:=ns-1; t:=t-rad;
        until ns = 0;
        t:=0-t;
        writeln(' t=', t:0:3);
      end;
  until xin < 0;
  writeln('fine')
end.

Nidhogg
beg0: è uguale a 2^(-26) e si usa per la doppia precisione del floating point (Credo).

Ciao, Ermanno.

tony19
d'accordo, ma a che serve quel 2^-26?
questo è il problema.
(la precisione, come dice la "const", è "extended", non "doppia")

grazie per l'attenzione!
hai provato a farlo girare?
magari con sqrt(0.0001) o sqrt(100000)
tony

Nidhogg
Per "0,0001" la radice è 0,010 -> ESATTA
Per "100000" la radice è 316,22776601683793319988935444327 -> Errata di poco.

Per la costante: Extended va da 3.6 x 10^-4951 a 1.1 x 10^4932 con precisione 19-20 cifre. L'occupazione è di 10 bytes. Penso sia questa la risposta.

Ciao Tony, Sei un grande!.

Ermanno.

tony19
> Per "100000" la radice è 316,22776601683793319988935444327 -> Errata di poco.

il risultato che dà il mio macinino è 316,228 che è l'arrotondamento di quello esatto.
io promettevo 2 decimali e mezzo, intendendo che il terzo non è garantito; e in questo caso il risultato eccede la promessa.
prova con altri numeri; è molto lento sulla tua macchina?

> Per la costante: Extended va da 3.6 x 10^-4951 a 1.1 x 10^49302
> con precisione 19-20 cifre. L'occupazione è di 10 bytes.
> Penso sia questa la risposta.

corretto; ma non era questa la domanda.
che è: a che serve in quel macinino quella strampalata costante ?

> Ciao Tony, Sei un grande!.

di statura: passo di un po' il metro e 80

tony

Nidhogg
Ora la radice quadrata di 100000 è 316,228. Chissà perchè prima era errata.
Per la costante sinceramente non saprei? Centra con una certa epsilon?

Ciao, Ermanno.

tony19
grazie della segnalazione !!! (ti ricordi quanto veniva, prima?)
quote:
Ora la radice quadrata di 100000 è 316,228. Chissà perchè prima era errata. [leonardo]

è sintomatica di qualche variabile non inizializzata dal programma, (ereditando la porcheria che trova in memoria); non dovrebbe mai capitare; mi metto a cercarla!

> Per la costante sinceramente non saprei? Centra con una certa epsilon?
no, non c'entra;
ti metto sulla strada: modifica quella riga in:
"const beg0 :extended =-1; n=1;"
e prova il macinino; che cosa succede?

tony

Nidhogg
Ho capito serve per i decimali, giusto?

Ciao, Ermanno.

tony19
esatto!
con, risp., -1 e 1 hai il problema originale di karl
con frazioni hai i decimali.

avevo cominciato con -0.01 e 10 per avere 1 decimale
e poi con -1/10^6 e 1000 per 3 decimali, etc.
accorgendomi che 1/10^6 in notazione binaria floating point
non è un numero esatto, con conseguente trascinamento di errori.

allora sono passato a -1/16 e 4 per 1 decimale
affinando fino all'attuale -1/2^26 e 2^13

nota che potresti lavorare in base 3, imperfetta come la 10:
prova con -1/3^16 e 3^8 (con taanti decimali): dovresti avere risultati equivalenti

divertente, no?
tony

p.s. mi rendo conto, nonostante l'help aperto, che non riesco a scrivere 3*10^n in pascal:
non mi accetta il segno "^" nè il doppio ** del fortran
come si fa? sono proprio a zero, vedi!

Nidhogg
In pascal non esiste l'elevamento a potenza, cioè il simbolo ^.

Ciao, Ermanno.

tony19
ah, non ero cieco!
questa poi non me la aspettavo da un linguaggio così "intellettuale"!
e come si aggira l'ostacolo, con una funzione?

tony

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.