Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

[C] Funzione di calcolo della radice quadrata di un intero

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[31] Re: [C] Funzione di calcolo della radice quadrata di un inte

Messaggioda Foto Utentedaniele1996 » 4 mag 2014, 1:58

Scusate se rianimo questo post, (premetto che non sono nessuno per dirlo) ma non sarebbe meglio metterlo in cima alle discussioni? in quel riquadro messo separato? secondo me sarebbe meglio... oppure linkarlo in un singolo topic insieme ad altri link che possono tornar utili per raggiungere topic del genere... alla fin fine può tornar utile a tutti!
Avatar utente
Foto Utentedaniele1996
570 2 7 11
Sostenitore
Sostenitore
 
Messaggi: 1143
Iscritto il: 29 ago 2011, 11:29

1
voti

[32] Re: [C] Funzione di calcolo della radice quadrata di un inte

Messaggioda Foto UtenteTardoFreak » 23 gen 2015, 21:39

Ieri ho scoperto che l' analisi di correttezza parziale del calcolo della radice con il metodo babilonese è stato oggetto di lezione nel di programmazione 1 corso A di informatica (unito) 2014/2015.
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,4k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15764
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

0
voti

[33] Re: [C] Funzione di calcolo della radice quadrata di un inte

Messaggioda Foto Utenteangel99 » 23 gen 2015, 23:17

Ciao Freak.

Premetto che il C lo uso ben poco dato che scrivo programmini semplici in assembler, quindi è possibile stia dicendo una castroneria. Guardavo questa parte del programma che hai scritto e mi domandavo il perché di quel condizionale all'interno del loop

Codice: Seleziona tutto
// calcola il numero di bit di n
  i = 0;
  val = n;
  do
  {
    val = val >> 1;
    if (val) i++;
  } while (val);


Visto che in caso di false si esce subito dal loop, non si potrebbe partire da -1 invece che da 0 e togliere il confronto che fa perdere tempo ad ogni interazione? Così per intenderci

Codice: Seleziona tutto
// calcola il numero di bit di n
  i = -1;
  val = n;
  do
  {
    val = val >> 1;
    i++;
  } while (val);


E' probabile che abbia detto una castronata, non te la prendere.
Avatar utente
Foto Utenteangel99
3.516 1 4 11
Master
Master
 
Messaggi: 1149
Iscritto il: 23 gen 2015, 19:39

0
voti

[34] Re: [C] Funzione di calcolo della radice quadrata di un inte

Messaggioda Foto UtenteeAlucarD » 24 gen 2015, 12:30

non puoi scrivere -1 in un unsigned :mrgreen:
non grave perché potresti sottrarlo alla fine

per quanto mi riguarda è più lodevole che qualcuno abbia condiviso un risultato ottenuto
per di più ha risolto ilproblema della radice,nella radice del tempoche ci metteva prima (affermazione degna del sig Baggings :mrgreen: )

questa è da stampare e incorniciare :ok:


goodjob
E l’uomo si addormentò e nel sogno creò il mondo
Avatar utente
Foto UtenteeAlucarD
1.210 3 5
Expert
Expert
 
Messaggi: 561
Iscritto il: 4 lug 2014, 11:01

0
voti

[35] Re: [C] Funzione di calcolo della radice quadrata di un inte

Messaggioda Foto Utenteangel99 » 24 gen 2015, 16:43

Sapevo che c'era l'inghippo... ecco la correzione.

Codice: Seleziona tutto
/ calcola il numero di bit di n
  i = 0;
  val = n;
  do
  {
    val = val >> 1;
    i++;
  } while (val);
  n--;


E' una routine molto interessante (grazie Freak).
Appena posso la trascrivo in asm...
Avatar utente
Foto Utenteangel99
3.516 1 4 11
Master
Master
 
Messaggi: 1149
Iscritto il: 23 gen 2015, 19:39

2
voti

[36] Re: [C] Funzione di calcolo della radice quadrata di un inte

Messaggioda Foto UtenteTardoFreak » 29 gen 2015, 19:54

Visto che oggi ho ripreso questa routine integrerò questo post o con una versione aggiornata o con l' output in assembler per il Cortex-M3.
Stay tuned :mrgreen:
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,4k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15764
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

0
voti

[37] Re: [C] Funzione di calcolo della radice quadrata di un inte

Messaggioda Foto UtentePietroBaima » 29 gen 2015, 20:03

ficus!
Generatore codice per articoli:
nomi
emoticon
citazioni
formule latex

Io capisco le cose per come le scrivete. Per esempio: K sono kelvin e non chilo, h.z è la costante di Planck per zepto o per la zeta di Riemann e l'inverso di una frequenza non si misura in siemens.
Avatar utente
Foto UtentePietroBaima
77,1k 6 12 13
G.Master EY
G.Master EY
 
Messaggi: 9401
Iscritto il: 12 ago 2012, 1:20
Località: Londra

2
voti

[38] Re: [C] Funzione di calcolo della radice quadrata di un inte

Messaggioda Foto UtenteTardoFreak » 2 feb 2015, 17:35

Non ci ho ancora messo le mani ma ho voluto dare uno sguardo a come il compilatore lavora.
Come si può notare utilizzare un processore SERIO con un set d' istruzioni furbo porta a produrre codice macchina compatto. Una funzione come questa, se compilata per un 8bit avrebbe prodotto molto più codice macchina. Quindi è bene farsene una ragione e passare ai 32bit. :mrgreen:
Diciamo che fare i cicli che contano verso lo 0 avrebbero fatto risparmiare qualche istruzione, ma questo non avrebbe portato risultati apprezzabili.
Questo è l' output in assembler
Codice: Seleziona tutto
                  uintSqrt PROC
;;;130    // Utilizza il metodo di calcolo della radice babilonese
;;;131    uint32_t uintSqrt(uint32_t n) __pure
00012a  0001              MOVS     r1,r0
;;;132    {
00012c  d004              BEQ      |L1.312|
;;;133      uint32_t i,val;
;;;134     
;;;135      // se n vale 0 ritorna 0
;;;136      if (!n) return 0;
;;;137     
;;;138      // calcola il numero di bit di n
;;;139      i = 0;
00012e  2200              MOVS     r2,#0
                  |L1.304|
;;;140      val = n;
;;;141      do
;;;142      {
;;;143        val = val >> 1;
000130  0840              LSRS     r0,r0,#1
;;;144        if (val) i++;
000132  d003              BEQ      |L1.316|
000134  1c52              ADDS     r2,r2,#1
000136  e7fb              B        |L1.304|
                  |L1.312|
000138  2000              MOVS     r0,#0                 ;136
;;;145      } while (val);
;;;146     
;;;147      // assume val come 2^(i/2)
;;;148      if (!i) val=1; else val = 1 << (i>>1);
;;;149     
;;;150      // Calcola la radice babilonese.
;;;151      // 4 passaggi sono sufficienti
;;;152      for(i=0; i<4; i++) val = (val + n/val) >> 1;
;;;153     
;;;154      return val;
;;;155    }
00013a  4770              BX       lr
                  |L1.316|
00013c  b162              CBZ      r2,|L1.344|
00013e  0852              LSRS     r2,r2,#1              ;148
000140  2001              MOVS     r0,#1                 ;148
000142  4090              LSLS     r0,r0,r2              ;148
                  |L1.324|
000144  f05f0200          MOVS.W   r2,#0                 ;152
                  |L1.328|
000148  fbb1f3f0          UDIV     r3,r1,r0              ;152
00014c  4418              ADD      r0,r0,r3              ;152
00014e  0840              LSRS     r0,r0,#1              ;152
000150  1c52              ADDS     r2,r2,#1              ;152
000152  2a04              CMP      r2,#4                 ;152
000154  d3f8              BCC      |L1.328|
000156  4770              BX       lr
                  |L1.344|
000158  2001              MOVS     r0,#1                 ;148
00015a  e7f3              B        |L1.324|
;;;156   
                          ENDP


Poi ho voluto vedere come compila ottimizzando per le prestazioni.
Il compilatore ha deciso di smontare i cicli e tradurli in una serie di operazioni perché ancora conveniente in termini di occupazione di FLASH.
E questo manda a gambe all' aria tutte le disquisizioni su come ottimizzare a livello di sorgente. Ci pensa lui e lo fa molto ma molto bene. iOi iOi iOi
Con buona pace dei "vecchi" programmatori come il sottoscritto :(
Questo è l' output
Codice: Seleziona tutto
                  uintSqrt PROC
;;;130    // Utilizza il metodo di calcolo della radice babilonese
;;;131    uint32_t uintSqrt(uint32_t n) __pure
0001c4  2800              CMP      r0,#0
;;;132    {
;;;133      uint32_t i,val;
;;;134     
;;;135      // se n vale 0 ritorna 0
;;;136      if (!n) return 0;
;;;137     
;;;138      // calcola il numero di bit di n
;;;139      i = 0;
0001c6  bf1a              ITTE     NE
0001c8  2200              MOVNE    r2,#0
;;;140      val = n;
0001ca  4601              MOVNE    r1,r0
;;;141      do
;;;142      {
;;;143        val = val >> 1;
;;;144        if (val) i++;
;;;145      } while (val);
;;;146     
;;;147      // assume val come 2^(i/2)
;;;148      if (!i) val=1; else val = 1 << (i>>1);
;;;149     
;;;150      // Calcola la radice babilonese.
;;;151      // 4 passaggi sono sufficienti
;;;152      for(i=0; i<4; i++) val = (val + n/val) >> 1;
;;;153     
;;;154      return val;
;;;155    }
0001cc  4770              BXEQ     lr
                  |L1.462|
0001ce  0849              LSRS     r1,r1,#1              ;143
0001d0  bf18              IT       NE                    ;144
0001d2  1c52              ADDNE    r2,r2,#1              ;144
0001d4  d1fb              BNE      |L1.462|
0001d6  2a00              CMP      r2,#0                 ;148
0001d8  bf0f              ITEEE    EQ                    ;148
0001da  2101              MOVEQ    r1,#1                 ;148
0001dc  0851              LSRNE    r1,r2,#1              ;148
0001de  2201              MOVNE    r2,#1                 ;148
0001e0  fa02f101          LSLNE    r1,r2,r1              ;148
0001e4  fbb0f2f1          UDIV     r2,r0,r1              ;152
0001e8  4411              ADD      r1,r1,r2              ;152
0001ea  0849              LSRS     r1,r1,#1              ;152
0001ec  fbb0f2f1          UDIV     r2,r0,r1              ;152
0001f0  4411              ADD      r1,r1,r2              ;152
0001f2  0849              LSRS     r1,r1,#1              ;152
0001f4  fbb0f2f1          UDIV     r2,r0,r1              ;152
0001f8  4411              ADD      r1,r1,r2              ;152
0001fa  0849              LSRS     r1,r1,#1              ;152
0001fc  fbb0f0f1          UDIV     r0,r0,r1              ;152
000200  4408              ADD      r0,r0,r1              ;152
000202  0840              LSRS     r0,r0,#1              ;152
000204  4770              BX       lr
;;;156   
                          ENDP


Inoltre questi esempi dimostrano la (quasi) totale inutilità di programmare in assembler, con buona pace di coloro che lo amano ancora. :mrgreen:
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,4k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15764
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

Precedente

Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 3 ospiti