Æò¹æ±ÙÀÇ °è»ê


ÇÔ¼ö¸í
squareRoot  1 ¿¡¼­ 99 ÀÇ »çÀÌÀÇ Æò¹æ±ÙÀÇ °ªÀ» ´ÙÀÚ¸®¼ö·Î »êÃâÇÑ´Ù.
Çü½Ä
int squareRoot(int *data, int keta, int n);
Àμö
data  (Ãâ·Â) Æò¹æ±ÙÀÇ °ªÀÌ 10Áø 4ÀÚ¸®¼ö¾¿ µé¾î°£ Á¤¼öÀÇ ¹è¿­
keta  (ÀÔ·Â) ¼Ò¼öÁ¡ ÀÌÇÏÀÇ ÀÚ¸®¼öÀÇ ÁöÁ¤
n     (ÀÔ·Â) °è»êÇÏ·Á°í ÇÏ´Â Æò¹æ±ÙÀÇ 2½ÂÀÇ °ª
ÇÔ¼öÄ¡
Á¤»óÀûÀ¸·Î °è»êÇÒ ¼ö ÀÖ¾úÀ» ¶§¿¡, °è»ê °á°ú°¡ µÇ´Â data ÀÇ ±æÀÌ. ¿¡·¯ ¶§ 0.
ÁÖÀÇ »çÇ×

¿ë·Ê(squareRoot-test.c )
2 ÀÇ Æò¹æ±ÙÀ» ¼Ò¼öÁ¡ ÀÌÇÏ 1000ÀÚ¸®¼ö·Î ¿ä±¸ÇÏ´Â ¿¹
int data[1000];
squareRoot(data, 1000, 2);

2 ÀÇ Æò¹æ±ÙÀÇ °ª(¼Ò¼öÁ¡ ÀÌÇÏ1¸¸ ÀÚ¸®¼ö)
3 ÀÇ Æò¹æ±ÙÀÇ °ª(¼Ò¼öÁ¡ ÀÌÇÏ1¸¸ ÀÚ¸®¼ö)
5 ÀÇ Æò¹æ±ÙÀÇ °ª(¼Ò¼öÁ¡ ÀÌÇÏ1¸¸ ÀÚ¸®¼ö)
6 ÀÇ Æò¹æ±ÙÀÇ °ª(¼Ò¼öÁ¡ ÀÌÇÏ1¸¸ ÀÚ¸®¼ö)
7 ÀÇ Æò¹æ±ÙÀÇ °ª(¼Ò¼öÁ¡ ÀÌÇÏ1¸¸ ÀÚ¸®¼ö)
8 ÀÇ Æò¹æ±ÙÀÇ °ª(¼Ò¼öÁ¡ ÀÌÇÏ1¸¸ ÀÚ¸®¼ö)
10 ÀÇ Æò¹æ±ÙÀÇ °ª(¼Ò¼öÁ¡ ÀÌÇÏ1¸¸ ÀÚ¸®¼ö)

ÇÁ·Î±×·¥(squareRoot.c )
int squareRoot(int *data, int keta, int n)
{
    int  *pbuf, *qbuf, *tbuf;
    int  *pp, *qq, *tt;
    int  pketa, qketa;
    int  i;
    int  ret;
    static long p0[101] = {    /* p0*p0 = 4+n*q0*q0 */
        0,-1, 6726, 2702,   -2, 5778, 9602, 4048, 6726,   -3, 1442,
        7940, 2702, 1298,  898, 3842,   -4, 4354, 1154,  340, 5778,
        2525,  394, 2302, 9602,   -5,  102, 2702, 4048,  727,  482,
        3040, 6726, 2114, 4898, 1692,   -6,  146, 5474, 2498, 1442,
        4098,  674, 6964, 7940, 2207,48670L, 9214, 2702,   -7,  198,
        9998, 1298, 2599,  970,  178,   898,  302,39206L, 1060,3842,
        1523,  126, 4048,   -8,  258,   130,97684L, 4354, 623,  502,
        6960, 1154,4562498L, 7398,2702,  340, 6239,  106, 160, 5778,
          -9,  326,  164,  110, 6887, 20810, 3134,  394,1000002L, 1442,
        3148, 2302,  839,4286590L, 6082,9602,125619266L, 198,7940,-10 };
    static long q0[101] = {
        0,-1, 4756, 1560,   -2, 2584, 3920, 1530, 2378,   -3,  456,
        2394,  780,  360,  240,  992,   -4, 1056,  272,   78, 1292,
         551,   84,  480, 1960,   -5,   20,  520,  765,  135,   88,
         546, 1189,  368,  840,  286,   -6,   24,  888,  400,  228,
         640,  104, 1062, 1197,  329, 7176, 1344,  390,   -7,   28,
        1400,  180,  357,  132,   24,  120,   40, 5148,  138,  496,
         195,   16,  510,   -8,   32,   16,11934,  528,   75,   60,
         826,  136,534000L, 860,  312,   39,  711,   12,   18,  646,
          -9,   36,   18,   12,  747, 2244,  336,   42,106000L, 152,
         330,  240,   87,442128L, 624,  980,12754704L, 20, 798,  -10 };

    if (n < 1 || n > 100 || keta < 1) return 0;
    
    if (p0[n] < 0) {
        *data = -p0[n];
        return 1;
    }

    if (p0[n]*p0[n] ! = 4 + q0[n]*q0[n]*n)
        return 0;				/* Oh, my God !  */
    ret = 0;
    pbuf = qbuf = tbuf = NULL;
    pbuf = (int *) calloc(2*keta+3, sizeof(int));
    qbuf = (int *) calloc(keta+3, sizeof(int));
    tbuf = (int *) calloc(keta+3, sizeof(int));

    if (pbuf ! = NULL && qbuf ! = NULL && tbuf ! = NULL) {

        if (p0[n] > 10000)
             *pbuf = p0[n]%10000, *(pbuf+1) = p0[n]/10000, pketa = 2;
        else *pbuf = p0[n], pketa = 1;
        if (q0[n] > 10000)
             *qbuf = q0[n]%10000, *(qbuf+1) = q0[n]/10000, qketa = 2;
        else *qbuf = q0[n], qketa = 1;

        while (qketa*4 < keta) {
            /* q = p * q */
            qketa = mulf(tbuf, pbuf, pketa, qbuf, qketa);
            for (tt = tbuf, qq = qbuf, i = qketa; i > 0; i--) *qq++ = *tt++;

            /* p = p * p - 2 */
            pketa = mulf(tbuf, pbuf, pketa, pbuf, pketa);
            for (tt = tbuf, pp = pbuf, i = pketa; i > 0; i--) *pp++ = *tt++;
            *pbuf -= 2;
        }
        ret = divf(data, pbuf, pketa, qbuf, qketa, tbuf);
    }
    if (tbuf ! = NULL) free(tbuf);
    if (pbuf ! = NULL) free(qbuf);
    if (qbuf ! = NULL) free(pbuf);
    return ret;
}

/* mm <-- aa * bb */
static int mulf(int *mm, int *aa, int la, int *bb, int lb)
{
    int  i, j;
    int  *a, *b, *m;
    int  lm, ca;
    long x;

    for (m = mm, i = la + lb; i > 0; i--) *m++ = 0;

    for (b = bb, j = 0; j < lb; j++, b++) {
        for (ca = 0, a = aa, i = 0; i < la; i++) {
            x = *a++;
            x = x * *b + *(mm + i + j) + ca;
            *(mm + i + j) = x % 10000;
            ca = x / 10000;
        }
        *(mm + i + j) = ca;
    }
    return la + lb - (ca == 0);
}         

/* qq <-- aa / bb */
static int divf(int *qq, int *aa, int la, int *bb, int lb, int *tt)
{
    int  i;
    int  *a, *b, *q, *t, *s;
    int  ca, k, Q, lt, lq, m;
    long x;

    for (a = aa + la + lb, s = aa + la, i = la; i > 0; i--) *--a = *--s;
    for (i = lb; i > 0; i--) *--a = 0;
    la += lb;

    if ((k = 4999 / *(bb + lb - 1) + 1) > 1) {
        for (ca = 0, a = aa, t = tt, i = 0; i < la; i++) {
            x = (long) k * *a++ + ca;
            *t++ = x % 10000, ca = x / 10000;
        }
        *t = ca;
        la = i + (ca > 0);
        for (t = tt, a = aa, i = la; i > 0; i--) *a++ = *t++;

        for (ca = 0, b = bb, t = tt, i = 0; i < lb; i++) {
            x = (long) k * *b++ + ca;
            *t++ = x % 10000, ca = x / 10000;
        }
        *t = ca;
        lb = i + (ca > 0);
        for (t = tt, b = bb, i = lb; i > 0; i--) *b++ = *t++;
    }

    lq = la - lb + 1;
    for (q = qq, i = lq; i > 0; i--) *q++ = 0;

    while ((m = la) >= lb) {
        if (*(aa + la - 1) >= *(bb + lb - 1)) {
            for (a = aa + la - 1, b = bb + lb - 1; b ! = bb; a--, b--) 
                if (*a ! = *b) break;
            if (b == bb) {
                *(qq + la - lb) = 1;
                la -= lb;
                continue;
            } else if (*a > *b) {
                for (s = b, ca = 0, a = aa + la - lb, b = bb; b <= s; a++) {
                    *a -= *b++ + ca;
                    ca = 0;
                    if (*a < 0) *a += 10000, ca = 1;
                }
                while (*--a == 0) ;
                *(qq + la - lb) = 1;
                la = a - aa + 1;
                continue;
            }
            Q = 9999;
        } else Q = (10000L * *(aa+la-1) + *(aa+la-2)) / *(bb+lb-1);
        if (la == lb) break;
        
        for ( ; ; ) {
            if (Q == 1) {
                *(bb + lb) = 0;
                for (ca=0, a=aa+(la-lb-1), b=bb, i=lb; i >= 0; i--, a++) {
                    *a -= *b++ + ca;
                    ca = 0;
                    if (*a < 0) *a += 10000, ca = 1;
                }
                while (*--a == 0) ;
                la = a - aa + 1;
                break;
            }
            for (ca = 0, t = tt, b = bb, i = 0; i < lb; i++) {
                x = (long) Q * *b++ + ca;
                *t++ = x % 10000, ca = x / 10000;
            }
            *t = ca;
            lt = i + 1;
            for (a = aa + la - 1, t = tt + lt - 1; t ! = tt; a--, t--)
                if (*a ! = *t) break;
            if (t == tt) {
                la -= lt;
                break;
            } else if (*a > *t) {
                for (s=t, ca=0, a = aa+(la-lt), t = tt; t <= s; a++) {
                    *a -= *t++ + ca;
                    ca = 0;
                    if (*a < 0) *a += 10000, ca = 1;
                }
                while (*--a == 0) ;
                la = a - aa + 1;
                break;
            } else Q--;
        }
        *(qq + m - lb - 1) = Q;
    }
    if (*(qq + lq - 1) == 0) lq--;

    return lq;
}
¼³¸í
ÇÊ¿ä·Î ÇÏ´Â ÀÚ¸®¼ö ÀÌ»óÀ¸·Î, ÀÌÇÏÀÇ Á¡È­½Ä

¡¡¡¡¡¡¡¡pi+1 = pi2 - 2
¡¡¡¡¡¡¡¡qi+1 = pi qi

(À»)¸¦ °è»êÇØ, ¸¶Áö¸·À¸·Î, pi+1 / qi+1 ·Î Æò¹æ±ÙÀ» ¿ä±¸ÇÑ´Ù.

µ¡ºÙ¿© ÃʱâÄ¡ p0, q0 Àº Æç ¹æÁ¤½Ä p02 - M q02 = 4 ¸¦ ä¿î´Ù Á¤¼öÇØÀÌ´Ù. ´Ù¸¸, M ´Â °è»êÇÏ·Á°í ÇÏ´Â Æò¹æ±ÙÀÇ 2½ÂÀÇ °ª.

¼öÇÐÀû ±Í³³¹ýÀ¸·Î Áõ¸íÇÒ ¼ö ÀÖÁö¸¸, À§ÀÇ Á¡È­½Ä¿¡¼­ ¾òÀ» ¼ö ÀÖ´ø pi+1, qi+1 ¿¡ ÀÇÇØ,

¡¡¡¡¡¡¡¡pi+1 / qi+1 = (M + 4 / (pi qi)2)1 / 2

µÈ´Ù. µû¶ó¼­ Æò¹æ±ÙÀÇ °è»ê¿¡ ´ëÇØ, º»¾Ë°í¸®ÁòÀÇ ¹æ¹ý¿¡¼­´Â ´ºÅϹýµî ´Ù¸¥ ¹æ¹ýº¸´Ù È¿À²ÀÌ ÁÁ°í, ¸îÂ÷·ÊÀÇ °è»êÀ¸·Î ÇÊ¿ä·Î ÇÏ´Â Á¤¹ÐµµÀÇ °ÍÀ» ¾òÀ» ¼ö ÀÖ´Ù.

°ü·Ã ÇÔ¼ö
Æç ¹æÁ¤½ÄÀÇ ÃÖ¼ÒÇØ