square root: improvement on square root seed

This commit is contained in:
2021-08-13 11:53:56 +02:00
parent 4cf3fb610a
commit 01dd79be15

View File

@@ -1,5 +1,10 @@
#include "square_root.h" #include "square_root.h"
/* V1: initial version
* V2: fix end condition: fail when i/2 < sqrt(i), for instance for i=2
* V3: improve seed determination: 60-70% improvement.
*/
/* See GNUmakefile in following link for explanation /* See GNUmakefile in following link for explanation
* https://exercism.io/my/solutions/103b2f7d92db42309c1988030f5202c7 * https://exercism.io/my/solutions/103b2f7d92db42309c1988030f5202c7
*/ */
@@ -8,6 +13,8 @@
#include <stdlib.h> #include <stdlib.h>
#endif #endif
#define NBITS (sizeof(unsigned) * 8)
/* Newton's method: /* Newton's method:
* https://en.wikipedia.org/wiki/Newton%27s_method#Square_root * https://en.wikipedia.org/wiki/Newton%27s_method#Square_root
* return the largest integer equal or less than i square root. * return the largest integer equal or less than i square root.
@@ -15,30 +22,34 @@
unsigned square_root(unsigned i) unsigned square_root(unsigned i)
{ {
unsigned sq, sq2; unsigned sq, sq2;
unsigned j;
long max;
if (i<=1) /* 0 and 1 */ if (i<=1) /* 0 and 1 */
return i; return i;
sq = i/2; /* we take i/2 as initial seed */ //nbits = (sizeof(unsigned) * 8);
sq2 = ((i/sq) + sq) / 2; /* first iteration */ for (j = 4, max = 16L;; j += 2, max <<= 2L) {
if (j >= NBITS || i <= max) {
while (sq2 != sq) { sq2 = (1L << (j >> 1));
sq = sq2; break;
sq2 = ((i/sq) + sq) /2; /* next iteration */ }
} }
do {
sq = sq2;
sq2 = ((i/sq) + sq) / 2; /* next iteration */
} while (sq2<sq);
return sq; return sq;
} }
#ifdef UNIT_TEST #ifdef UNIT_TEST
int main(int ac, char **av) int main(int ac, char **av)
{ {
int arg=1; unsigned i, j;
unsigned i;
for (; arg<ac; ++arg) { if (ac && *av)
i=atol(av[arg]); for (i=0; i<100000000; ++i)
printf("sqrt(%u)=%u\n", i, square_root(i)); square_root(65025);
} printf("sq=%u\n", square_root(65536));
} }
#endif #endif