square root: improvement on square root seed
This commit is contained in:
@@ -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
|
||||||
|
Reference in New Issue
Block a user