음이 아닌 실수 A 의 평방근 sqrt(A) 를 구하는 Heron 의 방법:

        반복함수  g(x) = (x + A/x) / 2   를 이용

 

실수 A 의 n제곱근 root(n, A) 를 구하는 Newton-Raphson 의 방법

        반복함수  g(x) = ((n-1)*x + A/(x**(n - 1))) / n    를 이용

n = 2 인 경우에는 Newton-Raphson 의 방법이 Heron 의 방법과 동일하다.

(참조. http://en.wikipedia.org/wiki/Newton's_method )

 

C# 언어에는 System 모듈에 지수 계산 함수 Math.Pow(double, double) 가 이미 구현되어 있다. 하지만 차후 필요한 데가 있을 것 같아서 이와 유사한 n 제곱 함수와 n 제곱근 함수를 구현해 보았다.

지수가 정수인 거듭제곱을 계산하는  함수도 nPow(), gPow, mPow() 세 개 구현해 놓았는데, 이들 세 함수는 절차적 언어의 성능상 재귀호출이 아니고 단순 반복 기법을 사용하는 함수이다. 이 세 함수 중 mPow() 의 성능이 가장 우수하다. 큰 지수의 경우 for 반복문의 반복회수를 따져 보면 성능 비교를 할 수 있을 것이다. (성능 비교를 위해 세 가지를 모두 소스에 남겨 두었다.) mPow() 함수는 n 제곱근을 구하는 재귀함수 newtonNthRoot(int, double) 의 구현에 사용되기도 한다. if ... else ... 구문이 많아 소스가 복잡하게 보일지 모르겠으나 이는 밑수나 지수가 음수이거나 0인 경우의 처리를 위함이다. 구현된 모든 함수의 구현에는 예외상황(예를 들어, 음수의 짝수 제곱근 같은 예외상황) 처리 과정이 있다.

아래의 소스는 대부분 버전의 비쥬얼 스튜디오의 C# 컴파일러로 컴파일 되고 실행되게 작성된 소스이다.

소스 첫 부분에

        private const int MAX_ITER = 20000;
        private const double M_EPSILON = 1.0e-15;

라고 선언하였으니 변수 MAX_ITER 와 M_EPSILON 는 (타입을 갖는) 상수로 선언되었다. const 예약어가 붙으면 static 예약어는 동시에 붙일 수 없다. Java 언어로는 상수를 선언할 방법이 없지만 C# 언어로는 이와 같이 const 예약어(키워드)를 이용하여 상수를 선언할 수 있다.

// Filename: TestNthRootApp.cs
//
//            Approximate square roots, cubic roots and n-th roots of a given number.
//
// Compile: csc TestNthRootApp.cs
// Execute: TestNthRootApp
//
// Date: 2013. 1. 6.
// Copyright (c) 2013 PH Kim  (pkim __AT__ scripts.pe.kr)


using System;

namespace TestApproximate
{

    public class TestNthRootApp {

        private const int MAX_ITER = 20000;
        private const double M_EPSILON = 1.0e-15;

        /**
         * Compute the n-th root of x to a given scale, x > 0.
         */
        public static double nPow(double a, int n) {
            if (n > 0) {
                if (n == 1)
                    return a;
                else {
                    if (a == 0.0 || a == 1.0) {
                        return a;
                    }
                    else if (a == -1.0) {
                        if (n % 2 == 1)
                            return -1.0;
                        else
                            return 1.0;
                    }
                    else if (a < 0.0) {
                        if (n % 2 == 1)
                            return -nPow(-a, n);
                        else
                            return nPow(-a, n);
                    }
                    else {
                        double y = 1.0;
                        for (int i = 0; i < n; i++) {
                            y *= a;
                        }
                        return y;
                    }
                }
            }
            else if (n == 0) {
                return 1.0;
            }
            else {      //  when n < 0
                if (a == 0.0)
                    throw new Exception("Negative powering exception of zero.");
                else {
                     if (n == -1)
                         return 1.0/a;
                     else
                         return 1.0/nPow(a, -n);
                 }
             }
        }

 

        /**
         * Compute the n-th root of x to a given scale, x > 0.
         */
        public static double gPow(double a, int n) {
            if (n > 0) {
                if (n == 1)
                    return a;
                else {
                    if (a == 0.0 || a == 1.0) {
                        return a;
                    }
                    else if (a == -1.0) {
                        if (n % 2 == 1)
                            return -1.0;
                        else
                            return 1.0;
                    }
                    else if (a < 0.0) {
                        if (n % 2 == 1)
                            return -gPow(-a, n);
                        else
                            return gPow(-a, n);
                    }
                    else {

                        double y = 1.0;
                        double r = a;
                        int m = 8*4 - 1;            ///  8*sizeof(int) - 1;
                        int one = 1;
                        for (int i = 0; i < m; i++) {
                            if ((n & one) == 0) {
                                y *= 1.0;
                            }
                            else {
                                y *= r;
                            }
                            r = r*r;
                            one <<= 1;
                            if (one > n)
                                break;
                        }
                        return y;
                    }
                }
            }
            else if (n == 0) {
                return 1.0;
            }
            else {      //  when n < 0
                if (a == 0.0)
                    throw new Exception("Negative powering exception of zero.");
                else {
                    if (n == -1)
                        return 1.0/a;
                    else
                        return 1.0/gPow(a, -n);
                }
            }
        }


        /**
         * Compute the n-th root of x to a given scale, x > 0.
         */
        public static double mPow(double a, int n) {
            if (n > 0) {
                if (n == 1)
                    return a;
                else {
                    if (a == 0.0 || a == 1.0) {
                        return a;
                    }
                    else if (a == -1.0) {
                        if (n % 2 == 1)
                            return -1.0;
                        else
                            return 1.0;
                    }
                    else if (a < 0.0) {
                        if (n % 2 == 1)
                            return -mPow(-a, n);
                        else
                            return mPow(-a, n);
                    }
                    else {

                        double y = 1.0;
                        double r = a;
                        int m = n;
                        while (m > 0) {
                            if ((m & 0x1) == 1) {
                                y *= r;
                            }
                            r = r*r;
                            m >>= 1;
                        }
                        return y;
                    }
                }
            }
            else if (n == 0) {
                return 1.0;
            }
            else {      //  when n < 0
                if (a == 0.0)
                    throw new Exception("Negative powering exception of zero.");
                else {
                    if (n == -1)
                        return 1.0/a;
                    else
                        return 1.0/mPow(a, -n);
                }
            }
        }

 

        /**
         * Compute the square root of x to a given scale, x > 0.
         */
        public static double heronSqrt(double a) {
            if (a < 0.0) {
                throw new Exception("Cannot find the sqrt of a negative number.");
            }
            else if (a == 0.0 || a == 1.0) {
                return a;
            }
            else {
                double x1 = a;
                double x2 = (x1 + a/x1)/2.0;
                double er = x1 - x2;
                int counter = 0;
                while (x1 + er != x1) {
                    x1 = x2;
                    x2 = (x1 + a/x1)/2.0;
                    er = x1 - x2;
                    if (Math.Abs(er) <Math.Abs( M_EPSILON*x1))
                        break;
                    counter++;
                    if (counter > MAX_ITER)
                        break;
                }
                if (counter >= MAX_ITER)
                    throw new Exception("Inaccurate sqrt exception by too many iterations.");
                return x2;
            }
        }

        /**
         * Compute the cubic root of x to a given scale, x > 0.
         */
        public static double newtonCbrt(double a) {
            if (a == 0.0 || a == 1.0 || a == -1.0) {
                return a;
            }
            else if (a < 0.0) {
                return -newtonCbrt(-a);
            }
            else {
                double x1 = a;
                double x2 = (2.0*x1 + a/(x1*x1))/3.0;
                double er = x1 - x2;
                int counter = 0;
                while (x1 + er != x1) {
                    x1 = x2;
                    x2 = (2.0*x1 + a/(x1*x1))/3.0;
                    er = x1 - x2;
                    if (Math.Abs(er) <Math.Abs( M_EPSILON*x1))
                        break;
                    counter++;
                    if (counter > MAX_ITER)
                        break;
                }
                if (counter >= MAX_ITER)
                    throw new Exception("Inaccurate cbrt exception by too many iterations.");
                return x2;
            }
        }

        /**
         * Compute the n-th root of x to a given scale, x > 0.
         */
        public static double newtonNthRoot(int n, double a) {
            if (n == 0) {
                return 1.0;
            }
            else if (n == 1) {
                return a;
            }
            else if (n > 0) {
                if (a == 0.0 || a == 1.0) {
                    return a;
                }
                else if (a == -1.0) {
                    if (n % 2 == 1)
                        return a;
                    else
                        throw new Exception("Cannot find the even n-th root of a negative number.");
                }
                else if (a < 0.0) {
                    if (n % 2 == 1)
                        return -newtonNthRoot(n, -a);
                    else
                        throw new Exception("Cannot find the even n-th root of a negative number.");
                }
                else if (a < 1.0) {
                    return 1.0/newtonNthRoot(n, 1.0/a);
                }
                else {
                    double x1 = a;
                    double xn = mPow(x1, n - 1);
                    double x2 = ((n - 1)*x1 + a/xn)/n;
                    double er = x1 - x2;
                    int counter = 0;
                    while (x1 + er != x1) {
                        x1 = x2;
                        xn = mPow(x1, n - 1);
                        x2 = ((n - 1)*x1 + a/xn)/n;
                        er = x1 - x2;
                        if (Math.Abs(er) <Math.Abs( M_EPSILON*x1))
                            break;
                        counter++;
                        if (counter > MAX_ITER)
                            break;
                    }
                    if (counter >= MAX_ITER)
                        throw new Exception("Inaccurate n-th root exception by too many iterations.");
                    return x2;
                }
            }
            else {
                if (a == 0.0) {
                    throw new Exception("Cannot find the negative n-th root of zero.");
                }
                else {
                    return 1.0/newtonNthRoot(-n, a);
                }
            }
        }


        public static void Main(string[] args) {

            double x = 16.0;
            double u = Math.Sqrt(x);

            Console.WriteLine("[ Testing heronSqrt(double) ]--------------------");
            Console.WriteLine("x = " + x );
            Console.WriteLine("u = Sqrt(" + x + ") = " + u );
            double y = heronSqrt(x);
            Console.WriteLine("y = heronSqrt(" + x + ") = " + y );
            Console.WriteLine("y*y = " + y*y );
            Console.WriteLine();

            Console.WriteLine("[ Testing newtonCbrt(double) ]--------------------" );
            x = -216.0;
            Console.WriteLine("x = " + x );
            Console.WriteLine("-Exp(Log(-x)/3.0) = " + -Math.Exp(Math.Log(-x)/3.0) );
            double w = newtonCbrt(x);
            Console.WriteLine("w = newtonCbrt(" + x + ") = " + w );
            Console.WriteLine("w*w*w = " + w*w*w );
            Console.WriteLine();

            x = 729000000000.0;
            Console.WriteLine("x = " + x );
            Console.WriteLine("Exp(Log(x)/3.0) = " + Math.Exp(Math.Log(x)/3.0) );
            w = newtonCbrt(x);
            Console.WriteLine("w = newtonCbrt(" + x + ") = " + w );
            Console.WriteLine("w*w*w = " + w*w*w );
            Console.WriteLine();

            Console.WriteLine("[ Testing newtonNthRoot(int, double) ]--------------------" );
            double z = newtonNthRoot(3, x);
            Console.WriteLine("x = " + x );
            Console.WriteLine("z = newtonNthRoot(3, " + x + ") = " + z );
            Console.WriteLine("z*z*z = " + z*z*z );
            Console.WriteLine();

            x = 12960000000000000000.0;
            z = newtonNthRoot(4, x);
            Console.WriteLine("x = " + x );
            Console.WriteLine("z = newtonNthRoot(4, x) = newtonNthRoot(4, " + x + ") = " + z );
            Console.WriteLine("z*z*z*z = " + z*z*z*z );
            Console.WriteLine();

            x = 1.0/12960000000000000000.0;
            z = newtonNthRoot(4, x);
            Console.WriteLine("x = " + x );
            Console.WriteLine("Exp(Log(x)/4.0) = " + Math.Exp(Math.Log(x)/4.0) );
            Console.WriteLine("z = newtonNthRoot(4, x) = newtonNthRoot(4, " + x + ") = " + z );
            Console.WriteLine("z*z*z*z = " + z*z*z*z );
            Console.WriteLine();


            try {
                x = -4.0;
                Console.WriteLine("[ Test Exception heronSqrt(double) ]--------------------" );
                Console.WriteLine("x = " + x );
                Console.WriteLine("Calculating heronSqrt(" + x + ")" );
                y = heronSqrt(x);
                Console.WriteLine("y = heronSqrt(" + x + ") = " + y );
                Console.WriteLine("y*y = " + y*y );
                Console.WriteLine();
            }
            catch (Exception ex) {
                Console.WriteLine(ex.Message + "\n" + "Caught some exception in calculating heronSqrt(" + x + ")");
                Console.WriteLine();
            }


            try {
                x = -4.0;
                Console.WriteLine("[ Test Exception in newtonCbrt(double) ]--------------------" );
                Console.WriteLine("x = " + x );
                Console.WriteLine("Calculating newtonCbrt(" + x + ")" );
                y = newtonCbrt(x);
                Console.WriteLine("y = newtonCbrt(" + x + ") = " + y );
                Console.WriteLine("y*y*y = " + y*y*y );
                Console.WriteLine();
            }
            catch (Exception ex) {
                Console.WriteLine(ex.Message + "\n" + "Caught some exception in calculating newtonCbrt(" + x + ")");
                Console.WriteLine();
            }


            Console.WriteLine("[ Test calculations by powering ]-----------------------------" );
            x = 200.0;
            z = newtonNthRoot(10, x);
            Console.WriteLine("x = " + x );
            Console.WriteLine("Exp(Log(x)/10.0) = " + Math.Exp(Math.Log(x)/10.0) );
            Console.WriteLine("z = newtonNthRoot(10, x) = newtonNthRoot(10, " + x + ") = " + z );
            Console.WriteLine("Pow(z, 10) = " + Math.Pow(z, 10) );
            Console.WriteLine();

            x = 3001.0;
            z = newtonNthRoot(99, x);
            Console.WriteLine("x = " + x );
            Console.WriteLine("Exp(Log(x)/99.0) = " + Math.Exp(Math.Log(x)/99.0) );
            Console.WriteLine("z = newtonNthRoot(99, x) = newtonNthRoot(99, " + x + ") = " + z );
            Console.WriteLine("Pow(z, 99) = " + Math.Pow(z, 99) );
            Console.WriteLine();

            x = 3001.0;
            z = newtonNthRoot(-99, x);
            Console.WriteLine("x = " + x );
            Console.WriteLine("Exp(Log(x)/-99.0) = " + Math.Exp(Math.Log(x)/-99.0) );
            Console.WriteLine("z = newtonNthRoot(-99, x) = newtonNthRoot(-99, " + x + ") = " + z );
            Console.WriteLine("1.0/Pow(z, 99) = " + 1.0/Math.Pow(z, 99) );
            Console.WriteLine();


            Console.WriteLine("2.1**2.1 = Pow(2.1, 2.1) = "  + Math.Pow(2.1, 2.1) );
            Console.WriteLine("2.1**(-2.1) = Pow(2.1, -2.1) = "  + Math.Pow(2.1, -2.1) );
            Console.WriteLine("2.1**2.1 * 2.1**(-2.1) = Pow(2.1, 2.1) * Pow(2.1, -2.1) = "  + Math.Pow(2.1, 2.1)*Math.Pow(2.1, -2.1) );
            Console.WriteLine("2.1**2.1 = Exp(2.1*Log(2.1)) = "  + Math.Exp(2.1*Math.Log(2.1)) );
            Console.WriteLine("2.1**(-2.1) = Exp(-2.1*Log(2.1)) = " + Math.Exp(-2.1*Math.Log(2.1)) );
            Console.WriteLine("2.1**2.1 * 2.1**(-2.1) = Exp(2.1*Log(2.1)) * Exp(-2.1*Log(2.1)) = "  + Math.Exp(2.1*Math.Log(2.1)) * Math.Exp(-2.1*Math.Log(2.1)) );
            Console.WriteLine();


            int k = 301;
            x = -1.029;
            double t1 = nPow(x, k);
            double t2 = gPow(x, k);
            double t3 = mPow(x, k);
            Console.WriteLine("t1 = nPow(" + x + ", " + k + ") = " + t1 );
            Console.WriteLine("t2 = gPow(" + x + ", " + k + ") = " + t2 );
            Console.WriteLine("t3 = mPow(" + x + ", " + k + ") = " + t3 );
            Console.WriteLine("t1 / t2 = " + (t1 / t2) );
            Console.WriteLine("t1 - t2 = " + (t1 - t2) );
            Console.WriteLine("t1 == t2 ? " + ((t1 == t2) ? "yes" : "no") );
            Console.WriteLine("t1 / t3 = " + (t1 / t3) );
            Console.WriteLine("t1 - t3 = " + (t1 - t3) );
            Console.WriteLine("t1 == t3 ? " + ((t1 == t3) ? "yes" : "no") );
            Console.WriteLine("t2 / t3 = " + (t2 / t3) );
            Console.WriteLine("t2 - t3 = " + (t2 - t3) );
            Console.WriteLine("t2 == t3 ? " + ((t2 == t3) ? "yes" : "no") );
            Console.WriteLine();

            Console.WriteLine("Done.");
        }
    }
}

/*
Output:
[ Testing heronSqrt(double) ]--------------------
x = 16
u = Sqrt(16) = 4
y = heronSqrt(16) = 4
y*y = 16

[ Testing newtonCbrt(double) ]--------------------
x = -216
-Exp(Log(-x)/3.0) = -6
w = newtonCbrt(-216) = -6
w*w*w = -216

x = 729000000000
Exp(Log(x)/3.0) = 9000
w = newtonCbrt(729000000000) = 9000
w*w*w = 729000000000

[ Testing newtonNthRoot(int, double) ]--------------------
x = 729000000000
z = newtonNthRoot(3, 729000000000) = 9000
z*z*z = 729000000000

x = 1.296E+19
z = newtonNthRoot(4, x) = newtonNthRoot(4, 1.296E+19) = 60000
z*z*z*z = 1.296E+19

x = 7.71604938271605E-20
Exp(Log(x)/4.0) = 1.66666666666667E-05
z = newtonNthRoot(4, x) = newtonNthRoot(4, 7.71604938271605E-20) = 1.66666666666
667E-05
z*z*z*z = 7.71604938271605E-20

[ Test Exception heronSqrt(double) ]--------------------
x = -4
Calculating heronSqrt(-4)
Cannot find the sqrt of a negative number.
Caught some exception in calculating heronSqrt(-4)

[ Test Exception in newtonCbrt(double) ]--------------------
x = -4
Calculating newtonCbrt(-4)
y = newtonCbrt(-4) = -1.5874010519682
y*y*y = -4

[ Test calculations by powering ]-----------------------------
x = 200
Exp(Log(x)/10.0) = 1.69864646463425
z = newtonNthRoot(10, x) = newtonNthRoot(10, 200) = 1.69864646463425
Pow(z, 10) = 200

x = 3001
Exp(Log(x)/99.0) = 1.08423618932588
z = newtonNthRoot(99, x) = newtonNthRoot(99, 3001) = 1.08423618932588
Pow(z, 99) = 3001

x = 3001
Exp(Log(x)/-99.0) = 0.922308266265993
z = newtonNthRoot(-99, x) = newtonNthRoot(-99, 3001) = 0.922308266265993
1.0/Pow(z, 99) = 3001.00000000001

2.1**2.1 = Pow(2.1, 2.1) = 4.74963809174224
2.1**(-2.1) = Pow(2.1, -2.1) = 0.210542357266885
2.1**2.1 * 2.1**(-2.1) = Pow(2.1, 2.1) * Pow(2.1, -2.1) = 1
2.1**2.1 = Exp(2.1*Log(2.1)) = 4.74963809174224
2.1**(-2.1) = Exp(-2.1*Log(2.1)) = 0.210542357266885
2.1**2.1 * 2.1**(-2.1) = Exp(2.1*Log(2.1)) * Exp(-2.1*Log(2.1)) = 1

t1 = nPow(-1.029, 301) = -5457.92801577163
t2 = gPow(-1.029, 301) = -5457.92801577169
t3 = mPow(-1.029, 301) = -5457.92801577169
t1 / t2 = 0.999999999999989
t1 - t2 = 6.18456397205591E-11
t1 == t2 ? no
t1 / t3 = 0.999999999999989
t1 - t3 = 6.18456397205591E-11
t1 == t3 ? no
t2 / t3 = 1
t2 - t3 = 0
t2 == t3 ? yes

Done.
*/

 

 

 

Posted by Scripter
,

음이 아닌 실수 A 의 평방근 sqrt(A) 를 구하는 Heron 의 방법:

        반복함수  g(x) = (x + A/x) / 2   를 이용

 

실수 A 의 n제곱근 root(n, A) 를 구하는 Newton-Raphson 의 방법

        반복함수  g(x) = ((n-1)*x + A/(x**(n - 1))) / n    를 이용

n = 2 인 경우에는 Newton-Raphson 의 방법이 Heron 의 방법과 동일하다.

(참조. http://en.wikipedia.org/wiki/Newton's_method )

 

Java 언어에는 math.lang 패키지에 지수 계산 함수 Math.pow(double, double) 가 이미 구현되어 있다. 하지만 차후 필요한 데가 있을 것 같아서 이와 유사한 n 제곱 함수와 n 제곱근 함수를 구현해 보았다.

지수가 정수인 거듭제곱을 계산하는  함수도 nPow(), gPow, mPow() 세 개 구현해 놓았는데, 이들 세 함수는 절차적 언어의 성능상 재귀호출이 아니고 단순 반복 기법을 사용하는 함수이다. 이 세 함수 중 mPow() 의 성능이 가장 우수하다. 큰 지수의 경우 for 반복문의 반복회수를 따져 보면 성능 비교를 할 수 있을 것이다. (성능 비교를 위해 세 가지를 모두 소스에 남겨 두었다.) mPow() 함수는 n 제곱근을 구하는 재귀함수 newtonNthRoot(int, double) 의 구현에 사용되기도 한다. if ... else ... 구문이 많아 소스가 복잡하게 보일지 모르겠으나 이는 밑수나 지수가 음수이거나 0인 경우의 처리를 위함이다. 구현된 모든 함수의 구현에는 예외상황(예를 들어, 음수의 짝수 제곱근 같은 예외상황) 처리 과정이 있다.

아래의 소스는 대부분 버전의 JVM(자바가상기계) 위에서 컴파일 되고 실행되게 작성된 소스이다.

소스 첫 부분에

    final private static int MAX_ITER = 20000;
    final private static double M_EPSILON = 1.0e-15;

라고 선언하였으니 변수 MAX_ITER 와 M_EPSILON 는 상수는 아니지만 상수와 거의 같은 효과를 같는 클래스 소속 변수(스태틱 변수)이다. Java 언어에는 C 언어나 C++ 언어에서 말하는 상수 선언이 없다.

// Filename: TestNthRootApp.java
//
//            Approximate square roots, cubic roots and n-th roots of a given number.
//
// Compile: javac -d . TestNthRootApp.java
// Execute: java TestNthRootApp
//
// Date: 2013. 1. 6.
// Copyright (c) 2013 PH Kim  (pkim __AT__ scripts.pe.kr)


public class TestNthRootApp {

    final private static int MAX_ITER = 20000;
    final private static double M_EPSILON = 1.0e-15;

    /**
     * Compute the n-th root of x to a given scale, x > 0.
     */
    public static double nPow(double a, int n) {
        if (n > 0) {
            if (n == 1)
                return a;
            else {
                if (a == 0.0 || a == 1.0) {
                    return a;
                }
                else if (a == -1.0) {
                    if (n % 2 == 1)
                        return -1.0;
                    else
                        return 1.0;
                }
                else if (a < 0.0) {
                    if (n % 2 == 1)
                        return -nPow(-a, n);
                    else
                        return nPow(-a, n);
                }
                else {
                    double y = 1.0;
                    for (int i = 0; i < n; i++) {
                        y *= a;
                    }
                    return y;
                }
            }
        }
        else if (n == 0) {
            return 1.0;
        }
        else {      //  when n < 0
            if (a == 0.0)
                throw new RuntimeException("Negative powering exception of zero.");
            else {
                if (n == -1)
                    return 1.0/a;
                else
                    return 1.0/nPow(a, -n);
            }
        }
    }

 

    /**
     * Compute the n-th root of x to a given scale, x > 0.
     */
    public static double gPow(double a, int n) {
        if (n > 0) {
            if (n == 1)
                return a;
            else {
                if (a == 0.0 || a == 1.0) {
                    return a;
                }
                else if (a == -1.0) {
                    if (n % 2 == 1)
                        return -1.0;
                    else
                        return 1.0;
                }
                else if (a < 0.0) {
                    if (n % 2 == 1)
                        return -gPow(-a, n);
                    else
                        return gPow(-a, n);
                }
                else {

                    double y = 1.0;
                    double r = a;
                    int m = 8*4 - 1;            ///  8*sizeof(int) - 1;
                    int one = 1;
                    for (int i = 0; i < m; i++) {
                        if ((n & one) == 0) {
                            y *= 1.0;
                        }
                        else {
                            y *= r;
                        }
                        r = r*r;
                        one <<= 1;
                        if (one > n)
                            break;
                    }
                    return y;
                }
            }
        }
        else if (n == 0) {
            return 1.0;
        }
        else {      //  when n < 0
            if (a == 0.0)
                throw new RuntimeException("Negative powering exception of zero.");
            else {
                if (n == -1)
                    return 1.0/a;
                else
                    return 1.0/gPow(a, -n);
            }
        }
    }


    /**
     * Compute the n-th root of x to a given scale, x > 0.
     */
    public static double mPow(double a, int n) {
        if (n > 0) {
            if (n == 1)
                return a;
            else {
                if (a == 0.0 || a == 1.0) {
                    return a;
                }
                else if (a == -1.0) {
                    if (n % 2 == 1)
                        return -1.0;
                    else
                        return 1.0;
                }
                else if (a < 0.0) {
                    if (n % 2 == 1)
                        return -mPow(-a, n);
                    else
                        return mPow(-a, n);
                }
                else {

                    double y = 1.0;
                    double r = a;
                    int m = n;
                    while (m > 0) {
                        if ((m & 0x1) == 1) {
                            y *= r;
                        }
                        r = r*r;
                        m >>= 1;
                    }
                    return y;
                }
            }
        }
        else if (n == 0) {
            return 1.0;
        }
        else {      //  when n < 0
            if (a == 0.0)
                throw new RuntimeException("Negative powering exception of zero.");
            else {
                if (n == -1)
                    return 1.0/a;
                else
                    return 1.0/mPow(a, -n);
            }
        }
    }

 

    /**
     * Compute the square root of x to a given scale, x > 0.
     */
    public static double heronSqrt(double a) {
        if (a < 0.0) {
            throw new RuntimeException("Cannot find the sqrt of a negative number.");
        }
        else if (a == 0.0 || a == 1.0) {
            return a;
        }
        else {
            double x1 = a;
            double x2 = (x1 + a/x1)/2.0;
            double er = x1 - x2;
            int counter = 0;
            while (x1 + er != x1) {
                x1 = x2;
                x2 = (x1 + a/x1)/2.0;
                er = x1 - x2;
                if (Math.abs(er) < Math.abs(M_EPSILON*x1))
                    break;
                counter++;
                if (counter > MAX_ITER)
                    break;
            }
            if (counter >= MAX_ITER)
                throw new RuntimeException("Inaccurate sqrt exception by too many iterations.");
            return x2;
        }
    }

    /**
     * Compute the cubic root of x to a given scale, x > 0.
     */
    public static double newtonCbrt(double a) {
        if (a == 0.0 || a == 1.0 || a == -1.0) {
            return a;
        }
        else if (a < 0.0) {
            return -newtonCbrt(-a);
        }
        else {
            double x1 = a;
            double x2 = (2.0*x1 + a/(x1*x1))/3.0;
            double er = x1 - x2;
            int counter = 0;
            while (x1 + er != x1) {
                x1 = x2;
                x2 = (2.0*x1 + a/(x1*x1))/3.0;
                er = x1 - x2;
                if (Math.abs(er) < Math.abs(M_EPSILON*x1))
                    break;
                counter++;
                if (counter > MAX_ITER)
                    break;
            }
            if (counter >= MAX_ITER)
                throw new RuntimeException("Inaccurate cbrt exception by too many iterations.");
            return x2;
        }
    }

    /**
     * Compute the n-th root of x to a given scale, x > 0.
     */
    public static double newtonNthRoot(int n, double a) {
        if (n == 0) {
            return 1.0;
        }
        else if (n == 1) {
            return a;
        }
        else if (n > 0) {
            if (a == 0.0 || a == 1.0) {
                return a;
            }
            else if (a == -1.0) {
                if (n % 2 == 1)
                    return a;
                else
                    throw new RuntimeException("Cannot find the even n-th root of a negative number.");
            }
            else if (a < 0.0) {
                if (n % 2 == 1)
                    return -newtonNthRoot(n, -a);
                else
                    throw new RuntimeException("Cannot find the even n-th root of a negative number.");
            }
            else if (a < 1.0) {
                return 1.0/newtonNthRoot(n, 1.0/a);
            }
            else {
                double x1 = a;
                double xn = mPow(x1, n - 1);
                double x2 = ((n - 1)*x1 + a/xn)/n;
                double er = x1 - x2;
                int counter = 0;
                while (x1 + er != x1) {
                    x1 = x2;
                    xn = mPow(x1, n - 1);
                    x2 = ((n - 1)*x1 + a/xn)/n;
                    er = x1 - x2;
                    if (Math.abs(er) < Math.abs(M_EPSILON*x1))
                        break;
                    counter++;
                    if (counter > MAX_ITER)
                        break;
                }
                if (counter >= MAX_ITER)
                    throw new RuntimeException("Inaccurate n-th root exception by too many iterations.");
                return x2;
            }
        }
        else {
            if (a == 0.0) {
                throw new RuntimeException("Cannot find the negative n-th root of zero.");
            }
            else {
                return 1.0/newtonNthRoot(-n, a);
            }
        }
    }


    public static void main(String[] args) {

        double x = 16.0;
        double u = Math.sqrt(x);

        System.out.println("[ Testing heronSqrt(double) ]--------------------");
        System.out.println("x = " + x );
        System.out.println("u = sqrt(" + x + ") = " + u );
        double y = heronSqrt(x);
        System.out.println("y = heronSqrt(" + x + ") = " + y );
        System.out.println("y*y = " + y*y );
        System.out.println();

        System.out.println("[ Testing newtonCbrt(double) ]--------------------" );
        x = -216.0;
        System.out.println("x = " + x );
        System.out.println("-exp(log(-x)/3.0) = " + -Math.exp(Math.log(-x)/3.0) );
        double w = newtonCbrt(x);
        System.out.println("w = newtonCbrt(" + x + ") = " + w );
        System.out.println("w*w*w = " + w*w*w );
        System.out.println();

        x = 729000000000.0;
        System.out.println("x = " + x );
        System.out.println("exp(log(x)/3.0) = " + Math.exp(Math.log(x)/3.0) );
        w = newtonCbrt(x);
        System.out.println("w = newtonCbrt(" + x + ") = " + w );
        System.out.println("w*w*w = " + w*w*w );
        System.out.println();

        System.out.println("[ Testing newtonNthRoot(int, double) ]--------------------" );
        double z = newtonNthRoot(3, x);
        System.out.println("x = " + x );
        System.out.println("z = newtonNthRoot(3, " + x + ") = " + z );
        System.out.println("z*z*z = " + z*z*z );
        System.out.println();

        x = 12960000000000000000.0;
        z = newtonNthRoot(4, x);
        System.out.println("x = " + x );
        System.out.println("z = newtonNthRoot(4, x) = newtonNthRoot(4, " + x + ") = " + z );
        System.out.println("z*z*z*z = " + z*z*z*z );
        System.out.println();

        x = 1.0/12960000000000000000.0;
        z = newtonNthRoot(4, x);
        System.out.println("x = " + x );
        System.out.println("exp(log(x)/4.0) = " + Math.exp(Math.log(x)/4.0) );
        System.out.println("z = newtonNthRoot(4, x) = newtonNthRoot(4, " + x + ") = " + z );
        System.out.println("z*z*z*z = " + z*z*z*z );
        System.out.println();


        try {
            x = -4.0;
            System.out.println("[ Test Exception heronSqrt(double) ]--------------------" );
            System.out.println("x = " + x );
            System.out.println("Calculating heronSqrt(" + x + ")" );
            y = heronSqrt(x);
            System.out.println("y = heronSqrt(" + x + ") = " + y );
            System.out.println("y*y = " + y*y );
            System.out.println();
        }
        catch (Exception ex) {
            System.out.println(ex.getMessage() + "\n" + "Caught some exception in calculating heronSqrt(" + x + ")" );
            System.out.println();
        }


        try {
            x = -4.0;
            System.out.println("[ Test Exception in newtonCbrt(double) ]--------------------" );
            System.out.println("x = " + x );
            System.out.println("Calculating newtonCbrt(" + x + ")" );
             = newtonCbrt(x);
            System.out.println("y = newtonCbrt(" + x + ") = " + y );
            System.out.println("y*y*y = " + y*y*y );
            System.out.println();
        }
        catch (Exception ex) {
            System.out.println(ex.getMessage() + "\n" + "Caught some exception in calculating newtonCbrt(" + x + ")");
            System.out.println();
        }


        System.out.println("[ Test calculations by powering ]-----------------------------" );
        x = 200.0;
        z = newtonNthRoot(10, x);
        System.out.println("x = " + x );
        System.out.println("exp(log(x)/10.0) = " + Math.exp(Math.log(x)/10.0) );
        System.out.println("z = newtonNthRoot(10, x) = newtonNthRoot(10, " + x + ") = " + z );
        System.out.println("pow(z, 10) = " + Math.pow(z, 10) );
        System.out.println();

        x = 3001.0;
        z = newtonNthRoot(99, x);
        System.out.println("x = " + x );
        System.out.println("exp(log(x)/99.0) = " + Math.exp(Math.log(x)/99.0) );
        System.out.println("z = newtonNthRoot(99, x) = newtonNthRoot(99, " + x + ") = " + z );
        System.out.println("pow(z, 99) = " + Math.pow(z, 99) );
        System.out.println();

        x = 3001.0;
        z = newtonNthRoot(-99, x);
        System.out.println("x = " + x );
        System.out.println("exp(log(x)/-99.0) = " + Math.exp(Math.log(x)/-99.0) );
        System.out.println("z = newtonNthRoot(-99, x) = newtonNthRoot(-99, " + x + ") = " + z );
        System.out.println("1.0/pow(z, 99) = " + 1.0/Math.pow(z, 99) );
        System.out.println();


        System.out.println("2.1**2.1 = pow(2.1, 2.1) = "  + Math.pow(2.1, 2.1) );
        System.out.println("2.1**(-2.1) = pow(2.1, -2.1) = "  + Math.pow(2.1, -2.1) );
        System.out.println("2.1**2.1 * 2.1**(-2.1) = pow(2.1, 2.1) * pow(2.1, -2.1) = "  + Math.pow(2.1, 2.1)*Math.pow(2.1, -2.1) );
        System.out.println("2.1**2.1 = exp(2.1*log(2.1)) = "  + Math.exp(2.1*Math.log(2.1)) );
        System.out.println("2.1**(-2.1) = exp(-2.1*log(2.1)) = " + Math.exp(-2.1*Math.log(2.1)) );
        System.out.println("2.1**2.1 * 2.1**(-2.1) = exp(2.1*log(2.1)) * exp(-2.1*log(2.1)) = "  + Math.exp(2.1*Math.log(2.1)) * Math.exp(-2.1*Math.log(2.1)) );
        System.out.println();


        int k = 301;
        x = -1.029;
        double t1 = nPow(x, k);
        double t2 = gPow(x, k);
        double t3 = mPow(x, k);
        System.out.println("t1 = nPow(" + x + ", " + k + ") = " + t1 );
        System.out.println("t2 = gPow(" + x + ", " + k + ") = " + t2 );
        System.out.println("t3 = mPow(" + x + ", " + k + ") = " + t3 );
        System.out.println("t1 / t2 = " + (t1 / t2) );
        System.out.println("t1 - t2 = " + (t1 - t2) );
        System.out.println("t1 == t2 ? " + ((t1 == t2) ? "yes" : "no") );
        System.out.println("t1 / t3 = " + (t1 / t3) );
        System.out.println("t1 - t3 = " + (t1 - t3) );
        System.out.println("t1 == t3 ? " + ((t1 == t3) ? "yes" : "no") );
        System.out.println("t2 / t3 = " + (t2 / t3) );
        System.out.println("t2 - t3 = " + (t2 - t3) );
        System.out.println("t2 == t3 ? " + ((t2 == t3) ? "yes" : "no") );
        System.out.println();

        System.out.println("Done.");
    }
}

/*
[ Testing heronSqrt(double) ]--------------------
x = 16.0
u = sqrt(16.0) = 4.0
y = heronSqrt(16.0) = 4.0
y*y = 16.0

[ Testing newtonCbrt(double) ]--------------------
x = -216.0
-exp(log(-x)/3.0) = -6.000000000000001
w = newtonCbrt(-216.0) = -6.0
w*w*w = -216.0

x = 7.29E11
exp(log(x)/3.0) = 9000.000000000004
w = newtonCbrt(7.29E11) = 9000.0
w*w*w = 7.29E11

[ Testing newtonNthRoot(int, double) ]--------------------
x = 7.29E11
z = newtonNthRoot(3, 7.29E11) = 9000.0
z*z*z = 7.29E11

x = 1.296E19
z = newtonNthRoot(4, x) = newtonNthRoot(4, 1.296E19) = 60000.0
z*z*z*z = 1.296E19

x = 7.716049382716049E-20
exp(log(x)/4.0) = 1.666666666666666E-5
z = newtonNthRoot(4, x) = newtonNthRoot(4, 7.716049382716049E-20) = 1.6666666666
666667E-5
z*z*z*z = 7.716049382716051E-20

[ Test Exception heronSqrt(double) ]--------------------
x = -4.0
Calculating heronSqrt(-4.0)
Cannot find the sqrt of a negative number.
Caught some exception in calculating heronSqrt(-4.0)

[ Test Exception in newtonCbrt(double) ]--------------------
x = -4.0
Calculating newtonCbrt(-4.0)
y = newtonCbrt(-4.0) = -1.5874010519681994
y*y*y = -3.999999999999999

[ Test calculations by powering ]-----------------------------
x = 200.0
exp(log(x)/10.0) = 1.6986464646342472
z = newtonNthRoot(10, x) = newtonNthRoot(10, 200.0) = 1.6986464646342472
pow(z, 10) = 199.9999999999999

x = 3001.0
exp(log(x)/99.0) = 1.0842361893258805
z = newtonNthRoot(99, x) = newtonNthRoot(99, 3001.0) = 1.0842361893258805
pow(z, 99) = 3000.9999999999955

x = 3001.0
exp(log(x)/-99.0) = 0.9223082662659932
z = newtonNthRoot(-99, x) = newtonNthRoot(-99, 3001.0) = 0.9223082662659932
1.0/pow(z, 99) = 3001.000000000004

2.1**2.1 = pow(2.1, 2.1) = 4.749638091742242
2.1**(-2.1) = pow(2.1, -2.1) = 0.21054235726688475
2.1**2.1 * 2.1**(-2.1) = pow(2.1, 2.1) * pow(2.1, -2.1) = 0.9999999999999999
2.1**2.1 = exp(2.1*log(2.1)) = 4.749638091742242
2.1**(-2.1) = exp(-2.1*log(2.1)) = 0.21054235726688478
2.1**2.1 * 2.1**(-2.1) = exp(2.1*log(2.1)) * exp(-2.1*log(2.1)) = 1.0

t1 = nPow(-1.029, 301) = -5457.92801577163
t2 = gPow(-1.029, 301) = -5457.928015771692
t3 = mPow(-1.029, 301) = -5457.928015771692
t1 / t2 = 0.9999999999999887
t1 - t2 = 6.184563972055912E-11
t1 == t2 ? no
t1 / t3 = 0.9999999999999887
t1 - t3 = 6.184563972055912E-11
t1 == t3 ? no
t2 / t3 = 1.0
t2 - t3 = 0.0
t2 == t3 ? yes

Done.
*/


 

 

Posted by Scripter
,

음이 아닌 실수 A 의 평방근 sqrt(A) 를 구하는 Heron 의 방법:

        반복함수  g(x) = (x + A/x) / 2   를 이용

 

실수 A 의 n제곱근 root(n, A) 를 구하는 Newton-Raphson 의 방법

        반복함수  g(x) = ((n-1)*x + A/(x**(n - 1))) / n    를 이용

n = 2 인 경우에는 Newton-Raphson 의 방법이 Heron 의 방법과 동일하다.

(참조. http://en.wikipedia.org/wiki/Newton's_method )

 

C 언어와 C++ 언어에는 (math.h 를 인클루드하여 사용하는) 표준 수학 라이브러리에 지수 계산 함수 pow() 가 이미 구현되어 있다. 하지만 차후 필요한 데가 있을 것 같아서 이와 유사한 n 제곱 함수와 n 제곱근 함수를 구현해 보았다.

지수가 정수인 거듭제곱을 계산하는  함수도 nPow(), gPow, mPow() 세 개 구현해 놓았는데, 이들 세 함수는 절차적 언어의 성능상 재귀호출이 아니고 단순 반복 기법을 사용하는 함수이다. 이 세 함수 중 mPow() 의 성능이 가장 우수하다. 큰 지수의 경우 for 반복문의 반복회수를 따져 보면 성능 비교를 할 수 있을 것이다. (성능 비교를 위해 세 가지를 모두 소스에 남겨 두었다.) mPow() 함수는 n 제곱근을 구하는 재귀함수 newtonNthRoot(int, double) 의 구현에 사용되기도 한다. if ... else ... 구문이 많아 소스가 복잡하게 보일지 모르겠으나 이는 밑수나 지수가 음수이거나 0인 경우의 처리를 위함이다. 구현된 모든 함수의 구현에는 예외상황(예를 들어, 음수의 짝수 제곱근 같은 예외상황) 처리 과정이 있다.

아래의 소스는 Visual C++ 외에 g++ 로 컴파일해도 수정 없이 잘 되리라고 본다.

예외상황 처리 때문에, Visual C++ 로 컴파일 할 때는 /EHsc 옵션을 붙여 주어야 하고, g++ 로 컴파일할 때는 -fexceptions 옵션을 반드시 붙여 주어야 한다.

// Filename: testNthRoot.cpp
//
//            Approximate square roots, cubic roots and n-th roots of a given number.
//
// Compile: cl /EHsc testNthRoot.cpp
// Execute: testNthRoot
//
//  Or
//
// Compile:  g++ -o testNthRoot testNthRoot.cpp -fexceptions
// Execute: ./testNthRoot
//
// Date: 2013. 1. 6.
// Copyright (c) 2013 PH Kim  (pkim __AT__ scripts.pe.kr)

#include <stdio.h>
#include <iostream>
#include <cmath>
#include <cstring>
// #include <memory.h>
#include <exception>

using namespace std;

class CalcException: public exception
{
  virtual const char* what() const throw()
  {
    return "Not supported calculation exception";
  }
} cannotCalcEx;

class NotDefinedException: public exception
{
  virtual const char* what() const throw()
  {
    return "Not defined calculation exception";
  }
} notDefinedEx;

class MayInaccurateException: public exception
{
  virtual const char* what() const throw()
  {
    return "Inaccurate approximation by too many iterrations.";
  }
} inaccurateApproxEx;

 

#define MAX_ITER 20000
#define M_EPSILON 1.0e-15


/**
  * Compute the n-th root of x to a given scale, x > 0.
  */
double nPow(double a, int n)
{
    if (n > 0) {
        if (n == 1)
            return a;
        else {
            if (a == 0.0 || a == 1.0) {
                return a;
            }
            else if (a == -1.0) {
                if (n % 2 == 1)
                    return -1.0;
                else
                    return 1.0;
            }
            else if (a < 0.0) {
                if (n % 2 == 1)
                    return -nPow(-a, n);
                else
                    return nPow(-a, n);
            }
            else {
                double y = 1.0;
                for (int i = 0; i < n; i++) {
                    y *= a;
                }
                return y;
            }
        }
    }
    else if (n == 0) {
        return 1.0;
    }
    else {      //  when n < 0
        if (a == 0.0)
            // throw "Negative powering exception of zero.";
            throw cannotCalcEx;
        else {
            if (n == -1)
                return 1.0/a;
            else
                return 1.0/nPow(a, -n);
        }
    }
}

 

/**
  * Compute the n-th root of x to a given scale, x > 0.
  */
double gPow(double a, int n)
{
    if (n > 0) {
        if (n == 1)
            return a;
        else {
            if (a == 0.0 || a == 1.0) {
                return a;
            }
            else if (a == -1.0) {
                if (n % 2 == 1)
                    return -1.0;
                else
                    return 1.0;
            }
            else if (a < 0.0) {
                if (n % 2 == 1)
                    return -gPow(-a, n);
                else
                    return gPow(-a, n);
            }
            else {


                double y = 1.0;
                double r = a;
                int m = 8*sizeof(int) - 1;   // ignore the most significant bit which means the +/- sign.
                int one = 1;
                for (int i = 0; i < m; i++) {
                    if ((n & one) == 0) {
                        y *= 1.0;
                    }
                    else {
                        y *= r;
                    }
                    r = r*r;
                    one <<= 1;
                    if (one > n)
                        break;
                }
                return y;
            }
        }
    }
    else if (n == 0) {
        return 1.0;
    }
    else {      //  when n < 0
        if (a == 0.0)
            // throw "Negative powering exception of zero.";
            throw cannotCalcEx;
        else {
            if (n == -1)
                return 1.0/a;
            else
                return 1.0/gPow(a, -n);
        }
    }
}

 

/**
  * Compute the n-th root of x to a given scale, x > 0.
  */
double mPow(double a, int n)
{
    if (n > 0) {
        if (n == 1)
            return a;
        else {
            if (a == 0.0 || a == 1.0) {
                return a;
            }
            else if (a == -1.0) {
                if (n % 2 == 1)
                    return -1.0;
                else
                    return 1.0;
            }
            else if (a < 0.0) {
                if (n % 2 == 1)
                    return -mPow(-a, n);
                else
                    return mPow(-a, n);
            }
            else {


                double y = 1.0;
                double r = a;
                int m = n;
                while (m > 0) {
                    if ((m & 0x1) != 0) {
                        y *= r;
                    }
                    r = r*r;
                    m >>= 1;
                }
                return y;
            }
        }
    }
    else if (n == 0) {
        return 1.0;
    }
    else {      //  when n < 0
        if (a == 0.0)
            // throw "Negative powering exception of zero.";
            throw cannotCalcEx;
        else {
            if (n == -1)
                return 1.0/a;
            else
                return 1.0/mPow(a, -n);
        }
    }
}

 

/**
  * Compute the square root of x to a given scale, x > 0.
  */
double heronSqrt(double a)
{
    if (a < 0.0) {
        // throw "Cannot find the sqrt of a negative number.";
        throw notDefinedEx;
    }
    else if (a == 0.0 || a == 1.0) {
        return a;
    }
    else {
        double x1 = a;
        double x2 = (x1 + a/x1)/2.0;
        double er = x1 - x2;
        int counter = 0;
        while (x1 + er != x1) {
            x1 = x2;
            x2 = (x1 + a/x1)/2.0;
            er = x1 - x2;
            if (abs(er) < abs(M_EPSILON*x1))
                break;
            counter++;
            if (counter > MAX_ITER)
                break;
        }
        if (counter >= MAX_ITER)
            // throw "Inaccurate sqrt exception by too many iterations.";
            throw inaccurateApproxEx;
        return x2;
    }
}

/**
  * Compute the cubic root of x to a given scale, x > 0.
  */
double newtonCbrt(double a)
{
    if (a == 0.0 || a == 1.0 || a == -1.0) {
        return a;
    }
    else if (a < 0.0) {
        return -newtonCbrt(-a);
    }
    else {
        double x1 = a;
        double x2 = (2.0*x1 + a/(x1*x1))/3.0;
        double er = x1 - x2;
        int counter = 0;
        while (x1 + er != x1) {
            x1 = x2;
            x2 = (2.0*x1 + a/(x1*x1))/3.0;
            er = x1 - x2;
            if (abs(er) < abs(M_EPSILON*x1))
                break;
            counter++;
            if (counter > MAX_ITER)
                break;
        }
        if (counter >= MAX_ITER)
            // throw "Inaccurate cbrt exception by too many iterations.";
            throw inaccurateApproxEx;
        return x2;
    }
}

/**
  * Compute the n-th root of x to a given scale, x > 0.
  */
double newtonNthRoot(int n, double a)
{
    if (n == 0) {
        return 1.0;
    }
    else if (n == 1) {
        return a;
    }
    else if (n > 0) {
        if (a == 0.0 || a == 1.0) {
            return a;
        }
        else if (a == -1.0) {
            if (n % 2 == 1)
                return a;
            else
                // throw "Cannot find the even n-th root of a negative number.";
                throw notDefinedEx;
        }
        else if (a < 0.0) {
            if (n % 2 == 1)
                return -newtonNthRoot(n, -a);
            else
                // throw "Cannot find the even n-th root of a negative number.";
                throw notDefinedEx;
        }
        else if (a < 1.0) {
            return 1.0/newtonNthRoot(n, 1.0/a);
        }
        else {
            double x1 = a;
            double xn = mPow(x1, n - 1);
            double x2 = ((n - 1)*x1 + a/xn)/n;
            double er = x1 - x2;
            int counter = 0;
            while (x1 + er != x1) {
                x1 = x2;
                xn = mPow(x1, n - 1);
                x2 = ((n - 1)*x1 + a/xn)/n;
                er = x1 - x2;
                if (abs(er) < abs(M_EPSILON*x1))
                    break;
                counter++;
                if (counter > MAX_ITER)
                    break;
            }
            if (counter >= MAX_ITER)
                // throw "Inaccurate n-th root exception by too many iterations.";
                throw inaccurateApproxEx;
            return x2;
        }
    }
    else {
        if (a == 0.0) {
            // throw "Cannot find the negative n-th root of zero.";
            throw cannotCalcEx;
        }
        else {
            return 1.0/newtonNthRoot(-n, a);
        }
    }
}

 

int main()
{
    std:cout.precision(16);

    double x = 16.0;
    double u = sqrt(x);


    cout << "[ Testing heronSqrt(double) ]--------------------" << endl;
    cout << "x = " << x << endl;
    cout << "u = sqrt(" << x << ") = " << u << endl;
    double y = heronSqrt(x);
    cout << "y = heronSqrt(" << x << ") = " << y << endl;
    cout << "y*y = " << y*y << endl;
    cout << endl;

    cout << "[ Testing newtonCbrt(double) ]--------------------" << endl;
    x = -216.0;
    cout << "x = " << x << endl;
    cout << "-exp(log(-x)/3.0) = " << -exp(log(-x)/3.0) << endl;
    double w = newtonCbrt(x);
    cout << "w = newtonCbrt(" << x << ") = " << w << endl;
    cout << "w*w*w = " << w*w*w << endl;
    cout << endl;

    x = 729000000000.0;
    cout << "x = " << x << endl;
    cout << "exp(log(x)/3.0) = " << exp(log(x)/3.0) << endl;
    w = newtonCbrt(x);
    cout << "w = newtonCbrt(" << x << ") = " << w << endl;
    cout << "w*w*w = " << w*w*w << endl;
    cout << endl;

    cout << "[ Testing newtonNthRoot(int, double) ]--------------------" << endl;
    double z = newtonNthRoot(3, x);
    cout << "x = " << x << endl;
    cout << "z = newtonNthRoot(3, " << x << ") = " << z << endl;
    cout << "z*z*z = " << z*z*z << endl;
    cout << endl;

    x = 12960000000000000000.0;
    z = newtonNthRoot(4, x);
    cout << "x = " << x << endl;
    cout << "z = newtonNthRoot(4, x) = newtonNthRoot(4, " << x << ") = " << z << endl;
    cout << "z*z*z*z = " << z*z*z*z << endl;
    cout << endl;

    x = 1.0/12960000000000000000.0;
    z = newtonNthRoot(4, x);
    cout << "x = " << x << endl;
    cout << "exp(log(x)/4.0) = " << exp(log(x)/4.0) << endl;
    cout << "z = newtonNthRoot(4, x) = newtonNthRoot(4, " << x << ") = " << z << endl;
    cout << "z*z*z*z = " << z*z*z*z << endl;
    cout << endl;


    try {
        x = -4.0;
        cout << "[ Test Exception heronSqrt(double) ]--------------------" << endl;
        cout << "x = " << x << endl;
        cout << "Calculating heronSqrt(" << x << ")" << endl;
        y = heronSqrt(x);
        cout << "y = heronSqrt(" << x << ") = " << y << endl;
        cout << "y*y = " << y*y << endl;
        cout << endl;
    }
    // catch( char *str )    {
    catch( exception& ex )    {
        cout << ex.what() << endl << "Caught some exception in calculating heronSqrt(" << x << ")" << endl;
        cout << endl;
    }

    try {
        x = -4.0;
        cout << "[ Test Exception in newtonCbrt(double) ]--------------------" << endl;
        cout << "x = " << x << endl;
        cout << "Calculating newtonCbrt(" << x << ")" << endl;
        y = newtonCbrt(x);
        cout << "y = newtonCbrt(" << x << ") = " << y << endl;
        cout << "y*y*y = " << y*y*y << endl;
        cout << endl;
    }
    // catch( char *str )    {
    catch( exception& ex )    {
        cout << ex.what() << endl << "Caught some exception in calculating newtonCbrtrt(" << x <<  ")" << endl;
        cout << endl;
    }

    cout << "[ Test calculations by powering ]-----------------------------" << endl;
    x = 200.0;
    z = newtonNthRoot(10, x);
    cout << "x = " << x << endl;
    cout << "exp(log(x)/10.0) = " << exp(log(x)/10.0) << endl;
    cout << "z = newtonNthRoot(10, x) = newtonNthRoot(10, " << x << ") = " << z << endl;
    cout << "pow(z, 10) = " << pow(z, 10) << endl;
    cout << endl;

    x = 3001.0;
    z = newtonNthRoot(99, x);
    cout << "x = " << x << endl;
    cout << "exp(log(x)/99.0) = " << exp(log(x)/99.0) << endl;
    cout << "z = newtonNthRoot(99, x) = newtonNthRoot(99, " << x << ") = " << z << endl;
    cout << "pow(z, 99) = " << pow(z, 99) << endl;
    cout << endl;

    x = 3001.0;
    z = newtonNthRoot(-99, x);
    cout << "x = " << x << endl;
    cout << "exp(log(x)/-99.0) = " << exp(log(x)/-99.0) << endl;
    cout << "z = newtonNthRoot(-99, x) = newtonNthRoot(-99, " << x << ") = " << z << endl;
    cout << "1.0/pow(z, 99) = " << 1.0/pow(z, 99) << endl;
    cout << endl;

    cout << "2.1**2.1 = pow(2.1, 2.1) = "  << pow(2.1, 2.1) << endl;
    cout << "2.1**(-2.1) = pow(2.1, -2.1) = "  << pow(2.1, -2.1) << endl;
    cout << "2.1**2.1 * 2.1**(-2.1) = pow(2.1, 2.1) * pow(2.1, -2.1) = "  << pow(2.1, 2.1)*pow(2.1, -2.1) << endl;
    cout << "2.1**2.1 = exp(2.1*log(2.1)) = "  << exp(2.1*log(2.1)) << endl;
    cout << "2.1**(-2.1) = exp(-2.1*log(2.1)) = "  << exp(-2.1*log(2.1)) << endl;
    cout << "2.1**2.1 * 2.1**(-2.1) = exp(2.1*log(2.1)) * exp(-2.1*log(2.1)) = "  << exp(2.1*log(2.1)) * exp(-2.1*log(2.1)) << endl;
    cout << endl;


    int k = 301;
    x = -1.029;
    double t1 = nPow(x, k);
    double t2 = gPow(x, k);
    double t3 = mPow(x, k);
    cout << "t1 = nPow(" << x << ", " << k << ") = " << t1 << endl;
    cout << "t2 = gPow(" << x << ", " << k << ") = " << t2 << endl;
    cout << "t3 = mPow(" << x << ", " << k << ") = " << t3 << endl;
    cout << "t1 / t2 = " << (t1 / t2) << endl;
    cout << "t1 - t2 = " << (t1 - t2) << endl;
    cout << "t1 == t2 ? " << ((t1 == t2) ? "yes" : "no") << endl;
    cout << "t1 / t3 = " << (t1 / t3) << endl;
    cout << "t1 - t3 = " << (t1 - t3) << endl;
    cout << "t1 == t3 ? " << ((t1 == t3) ? "yes" : "no") << endl;
    cout << "t2 / t3 = " << (t2 / t3) << endl;
    cout << "t2 - t3 = " << (t2 - t3) << endl;
    cout << "t2 == t3 ? " << ((t2 == t3) ? "yes" : "no") << endl;
    cout << endl;

    cout << "Done." << endl;
}

/*
Output:
[ Testing heronSqrt(double) ]--------------------
x = 16
u = sqrt(16) = 4
y = heronSqrt(16) = 4
y*y = 16

[ Testing newtonCbrt(double) ]--------------------
x = -216
-exp(log(-x)/3.0) = -6.000000000000001
w = newtonCbrt(-216) = -6
w*w*w = -216

x = 729000000000
exp(log(x)/3.0) = 9000.000000000004
w = newtonCbrt(729000000000) = 9000
w*w*w = 729000000000

[ Testing newtonNthRoot(int, double) ]--------------------
x = 729000000000
z = newtonNthRoot(3, 729000000000) = 9000
z*z*z = 729000000000

x = 1.296e+019
z = newtonNthRoot(4, x) = newtonNthRoot(4, 1.296e+019) = 60000
z*z*z*z = 1.296e+019

x = 7.716049382716049e-020
exp(log(x)/4.0) = 1.666666666666666e-005
z = newtonNthRoot(4, x) = newtonNthRoot(4, 7.716049382716049e-020) = 1.666666666
666667e-005
z*z*z*z = 7.716049382716052e-020

[ Test Exception heronSqrt(double) ]--------------------
x = -4
Calculating heronSqrt(-4)
Not defined calculation exception
Caught some exception in calculating heronSqrt(-4)

[ Test Exception in newtonCbrt(double) ]--------------------
x = -4
Calculating newtonCbrt(-4)
y = newtonCbrt(-4) = -1.587401051968199
y*y*y = -3.999999999999999

[ Test calculations by powering ]-----------------------------
x = 200
exp(log(x)/10.0) = 1.698646464634247
z = newtonNthRoot(10, x) = newtonNthRoot(10, 200) = 1.698646464634247
pow(z, 10) = 199.9999999999999

x = 3001
exp(log(x)/99.0) = 1.084236189325881
z = newtonNthRoot(99, x) = newtonNthRoot(99, 3001) = 1.084236189325881
pow(z, 99) = 3000.999999999987

x = 3001
exp(log(x)/-99.0) = 0.9223082662659932
z = newtonNthRoot(-99, x) = newtonNthRoot(-99, 3001) = 0.9223082662659932
1.0/pow(z, 99) = 3001.000000000008

2.1**2.1 = pow(2.1, 2.1) = 4.749638091742242
2.1**(-2.1) = pow(2.1, -2.1) = 0.2105423572668848
2.1**2.1 * 2.1**(-2.1) = pow(2.1, 2.1) * pow(2.1, -2.1) = 0.9999999999999999
2.1**2.1 = exp(2.1*log(2.1)) = 4.749638091742242
2.1**(-2.1) = exp(-2.1*log(2.1)) = 0.2105423572668848
2.1**2.1 * 2.1**(-2.1) = exp(2.1*log(2.1)) * exp(-2.1*log(2.1)) = 1

t1 = nPow(-1.029, 301) = -5457.92801577163
t2 = gPow(-1.029, 301) = -5457.928015771692
t3 = mPow(-1.029, 301) = -5457.928015771692
t1 / t2 = 0.9999999999999887
t1 - t2 = 6.184563972055912e-011
t1 == t2 ? no
t1 / t3 = 0.9999999999999887
t1 - t3 = 6.184563972055912e-011
t1 == t3 ? no
t2 / t3 = 1
t2 - t3 = 0
t2 == t3 ? yes

Done.
*/

 

 

Posted by Scripter
,

역삼각함수란 삼각함수의 역함수를 의미하고,

역쌍곡선함수란 쌍곡선함수의 역함수를 의미한다.

수학에서 sin 함수의 역함수는 arcsin 으로 표기되는데,

 C 언어나 C++ 언어에서는 asin 함수로 구현되어 있다.

<gsl/gsl_math.h> 를 인클루드하면 gsl_math.h 가 자체적으로 <math.h> 를 또 인클루드하므로, <math.h> 를 별도로 인크루드할 필요가 없다.

sinh 와 cosh 의 역함수로 그냥 C 언어의 <math.h> 에서 정의된 asinhacosh 를 써도 되지만. 여기서는 <gsl/gsl_math.h> 에서 정의된 gsl_asinhgsl_acosh 를 써 보았다.

참고로 gsl 이라 함은 GNU Scientific Library 의 줄임글이다.

아래의 소스는 Visual C++ 또는 gcc 로 컴파일되는 소스이다. 실행 결과는 같다.

/*
 * Filename: testArcSineWithGSL.c
 *
 *    Require gsl 1.13 above and Visual C 2010
 *
 *     Or
 *
 *    Require gsl 1.13 above and Cygwin
 *
 * Compile: cl testArcSineWithGSL.c gsl.lib /MD
 * Execute: testArcSineWithGSL
 *
 *  Or
 *
 * Compile: gcc -Wall -I/usr/local/include -c testArcSineWithGSL.c
 *     Link: gcc -o testArcSineGSL -L/usr/local/lib testArcSineWithGSL.o -lgsl
 * Execute: ./testArcSineGSL
 *
 *
 * Date: 2013. 1. 10.
 * Copyright (c) pkim _AT_ scripts.pe.kr
 */

#include <stdio.h>
#include <gsl/gsl_math.h>   // This includes <math.h>


int main(void) {
    double x, y, u, v;

    x = -0.9;
    y = asin(x);
    printf("x = %g\n", x);
    printf("y = asin(%g) = %.9f\n", x, y);
    printf("sin(%.9f) = %g\n", y, sin(y));
    printf("\n");

    x = 1.1;
    u = gsl_acosh(x);
    v = gsl_asinh(x);
    printf("x = %g\n", x);
    printf("u = gsl_acosh(%g) = %.10f\n", x, u);
    printf("v = gsl_asinh(%g) = %.10f\n", x, v);
    printf("\n");

    printf("cosh(u) = cosh(%.10f) = %g\n", u, cosh(u));
    printf("sinh(v) = sinh(%.10f) = %g\n", v, sinh(v));

    return 0;
}

/*
Output:
x = -0.9
y = asin(-0.9) = -1.119769515
sin(-1.119769515) = -0.9

x = 1.1
u = gsl_acosh(1.1) = 0.4435682544
v = gsl_asinh(1.1) = 0.9503469298

cosh(u) = cosh(0.4435682544) = 1.1
sinh(v) = sinh(0.9503469298) = 1.1

*/

 

 

Posted by Scripter
,

역삼각함수란 삼각함수의 역함수를 의미하고,

역쌍곡선함수란 쌍곡선함수의 역함수를 의미한다.

수학에서 sin 함수의 역함수는 arcsin 으로 표기되는데,

Python 언어에서는 math.asin() 함수로 이미 구현되어 있다.

이를 사용하기 위해서는 import 구문

import math

가 있으면 된다. 그러나 scipy 나 numpy 모듈을 사용할 때는 얘기가 달라진다.

sin 함수의 역함수가 scipy 모듈에서는 scipy.arcsin 으로, numpy 모듈에서는 numpy.arcsin 으로 구현되어 있다. (asin 이 아니라 arcsin 임에 주의하자.) 한편 mpmath 모듈에서는 mpmath.asin 으로 구현되어 았다. 이들 이용하기 위해서는 import 구문

import scipy

또는

import numpy

또는

import mpmath

가 각각 필요하다.

다음의 첫 두 개 소스는 scipy 와 numpy 의 차이 이외에는  똑 같다.

 

[ scipy 모듈을 이용하는 Python 소스 ]

#!/usr/bin/env python
# -*- encoding: utf-8 -*-

# Filename: testArcSineWithScipy.py
#
#            Approximate square roots, cubic roots and n-th roots of a given number.
#
# Execute: python testArcSineWithScipy.py
#
# Date: 2013. 1. 9.
# Copyright (c) 2013 PH Kim  (pkim __AT__ scripts.pe.kr)

import scipy as sp

x = -0.9
y = sp.arcsin(x)
print "x = %g" % x
print "y = sp.arcsin(x) = sp.arcsin(%g) = %.9f" % (x, y)
print "sp.sin(y) = sp.sin(%.9f) = %g" % (y, sp.sin(y))
print

x = 1.1
u = sp.arccosh(x)
v = sp.arcsinh(x)
print "x = %g" % x
print "u = sp.arccosh(x) = sp.arccosh(%g) = %.10f" % (x, u)
print "v = sp.arcsinh(x) = sp.arcsinh(%g) = %.10f" % (x, v)
print

print "sp.cosh(u) = sp.cosh(%.10f) = %g" % (u, sp.cosh(u))
print "sp.sinh(v) = sp.sinh(%.10f) = %g" % (v, sp.sinh(v))

"""
Output:
x = -0.9
y = sp.arcsin(x) = sp.arcsin(-0.9) = -1.119769515
sp.sin(y) = sp.sin(-1.119769515) = -0.9

x = 1.1
u = sp.arccosh(x) = sp.arccosh(1.1) = 0.4435682544
v = sp.arcsinh(x) = sp.arcsinh(1.1) = 0.9503469298

sp.cosh(u) = sp.cosh(0.4435682544) = 1.1
sp.sinh(v) = sp.sinh(0.9503469298) = 1.1
"""

 

[ numpy 모듈을 이용하는 Python 소스 ]

#!/usr/bin/env python
# -*- encoding: utf-8 -*-

# Filename: testArcSineWithNumpy.py
#
#            Approximate square roots, cubic roots and n-th roots of a given number.
#
# Execute: python testArcSineWithNumpy.py
#
# Date: 2013. 1. 9.
# Copyright (c) 2013 PH Kim  (pkim __AT__ scripts.pe.kr)

import numpy as np

x = -0.9
y = np.arcsin(x)
print "x = %g" % x
print "y = np.arcsin(x) = np.arcsin(%g) = %.9f" % (x, y)
print "np.sin(y) = np.sin(%.9f) = %g" % (y, np.sin(y))
print

x = 1.1
u = np.arccosh(x)
v = np.arcsinh(x)
print "x = %g" % x
print "u = np.arccosh(x) = np.arccosh(%g) = %.10f" % (x, u)
print "v = np.arcsinh(x) = np.arcsinh(%g) = %.10f" % (x, v)
print

print "np.cosh(u) = np.cosh(%.10f) = %g" % (u, np.cosh(u))
print "np.sinh(v) = np.sinh(%.10f) = %g" % (v, np.sinh(v))

"""
Output:
x = -0.9
y = np.arcsin(x) = np.arcsin(-0.9) = -1.119769515
np.sin(y) = np.sin(-1.119769515) = -0.9

x = 1.1
u = np.arccosh(x) = np.arccosh(1.1) = 0.4435682544
v = np.arcsinh(x) = np.arcsinh(1.1) = 0.9503469298

np.cosh(u) = np.cosh(0.4435682544) = 1.1
np.sinh(v) = np.sinh(0.9503469298) = 1.1
"""

 

 

[ mpmath 모듈을 이용하는 Python 소스 ]

#!/usr/bin/env python
# -*- encoding: utf-8 -*-

# Filename: testArcSineWithMpmath.py
#
#            Approximate square roots, cubic roots and n-th roots of a given number.
#
# Execute: python testArcSineMpmath.py
#
# Date: 2013. 1. 9.
# Copyright (c) 2013 PH Kim  (pkim __AT__ scripts.pe.kr)

import mpmath as mp

x = -0.9
y = mp.asin(x)
print "x = %g" % x
print "y = mp.asin(%g) = %.9f" % (x, y)
print "mp.sin(y) = mp.sin(%.9f) = %g" % (y, mp.sin(y))
print

x = 1.1
u = mp.acosh(x)
v = mp.asinh(x)
print "x = %g" % x
print "u = mp.acosh(%g) = %.9f" % (x, u)
print "v = mp.asinh(%g) = %.9f" % (x, v)
print

print "mp.cosh(u) = mp.cosh(%.9f) = %g" % (u, mp.cosh(u))
print "mp.sinh(v) = mp.sinh(%.9f) = %g" % (u, mp.sinh(v))

 

 

 

Posted by Scripter
,

역삼각함수란 삼각함수의 역함수를 의미하고,

역쌍곡선함수란 쌍곡선함수의 역함수를 의미한다.

수학에서 sin 함수의 역함수는 arcsin 으로 표기되는데, Maxima 언어에서는 asin 함수로 구현되어 있다. 또한 Maxima 언어에는 쌍곡선함수 sinhcosh 의 역함수가 각각 asinhacosh 라는 이름으로 구현되어 있다.

첨고로 Maxima 의 Input 에서  ; 로 끝나는 명령은 명령의 수행 결과가 Output 으로 출력되고, $ 로 끝나는 줄은 Output 으로의 출력을 보류한다. 이 때는 disp() 나 printf() 등에 의한 명시적인 출력만 출력된다.

아래는 wxMaxima 를 이용하여 역삼각함수와 역쌍곡함수의 값을 계산하고 검증한 것이다.

Maxima 에서 다음 몇 줄만 입력하여 각 cell 마다 Ctrl + Enter 키를 눌러 실행하면 된다. 아니면 메뉴의 Cell -> Evaluate All Cells 를 택하면 한꺼번에 실행된다.

 

Posted by Scripter
,

역삼각함수란 삼각함수의 역함수를 의미하고,

역쌍곡선함수란 쌍곡선함수의 역함수를 의미한다.

수학에서 sin 함수의 역함수는 arcsin 으로 표기되는데, Mathematica 언어에서는 ArcSin 함수로 구현되어 있다. 또한 Mathematica 언어에는 쌍곡선함수 sinhcosh 의 역함수로 각각 ArcSinhArcCosh 가 구현되어 있다.

Mathematica Notebook 에서 다음 몇 줄만 입력하여 각 cell 마다 Shift + Enter 키를 눌러 실행하면 된다. SetPrecision 은 계산 과정과 출력에서 정확도의 유효수자 개수릉 지정하기 위해 사용되었다.

x = -0.9
y = SetPrecision[ArcSin[x], 10]

Sin[y]

x = 1.1
u = SetPrecision[ArcCosh[x], 10]
v = SetPrecision[ArcSinh[x], 10]

Cosh[u]
Sinh[v]

 

 

                     <* Notebook 의 각 cell 에 입력한 모습 *>

 

          <* Notebook 의 각 cell 마다 Shift + Enter 키를 눌러 결과를 확인한 모습 *>

 

 

 

Posted by Scripter
,

역삼각함수란 삼각함수의 역함수를 의미하고,

역쌍곡선함수란 쌍곡선함수의 역함수를 의미한다.

수학에서 sin 함수의 역함수는 arcsin 으로 표기되는데, Octave 언어에서는 asin 함수로 구현되어 있다.

또한 Gnuplot 언어에는 쌍곡선함수 sinhcosh 의 역함수로 각각 asinhacosh 가 구현되어 있지만, 비교를 위해 arcsinharccosh 라는 이름의 함수로 아래의 소스에 구현해 보았다.

소스 파일을 저장할 때 확장명을 plt 로 해도 되고 dem 으로 해도 된다. Gnuplot 에서 저정된 소스 파일을 load 하면 실행결과가 출력된다.

# Filename: estArcSine.plt
#
# Execute: load '저장경로/testArcSine.plt'
#
# Date: 2013. 1. 8.
# Copyright (c) PKim (pkim __AT__ scripts.pe.kr)

arccosh(x) = log(x + sqrt(x*x - 1))
arcsinh(x) = log(x + sqrt(x*x + 1))

x = -0.9
y = asin(x)
print "y = asin(", x, ") = ", y
print "sin(", y, ") = ", sin(y)
print ""

x = 1.1
u = acosh(x)
print "u = acosh(", x, ") = ", u
print "cosh(", u, ") = ", cosh(u)
print ""

v = asinh(x)
print "v = asinh(", x, ") = ", v
print "sinh(", v, ") = ", sinh(v)
print ""

print "arccosh(", x, ") = ", arccosh(x)
print "arcsinh(", x, ") = ", arcsinh(x)
print ""

##################################
# Output:
# -------------------------------------
# y = asin(-0.9) = -1.11976951499863
# sin(-1.11976951499863) = -0.9
#
# u = acosh(1.1) = 0.443568254385115
# cosh(0.443568254385115) = 1.1
#
# v = asinh(1.1) = 0.950346929821134
# sinh(0.950346929821134) = 1.1
#
# arccosh(1.1) = 0.443568254385115
# arcsinh(1.1) = 0.950346929821134  
##################################

 

 

        <* 저장된 Gnuplot 에서 소스 파일 testArcSine.plt 를 load 하여 실행한 화면 *>

 

 

 

 

Posted by Scripter
,

역삼각함수란 삼각함수의 역함수를 의미하고,

역쌍곡선함수란 쌍곡선함수의 역함수를 의미한다.

수학에서 sin 함수의 역함수는 arcsin 으로 표기되는데, Octave 언어에서는 asin 함수로 구현되어 있다.

또한 Octave 언어에는 쌍곡선함수 sinhcosh 의 역함수로 각각 asinhacosh 가 구현되어 있지만, 비교를 위해 arcsinharccosh 라는 이름의 함수로 아래의 소스에 구현해 보았다.

%{
% Filename: testArcSine.m
%
% Execute: octave -qf testArcSine.m
%
% Date: 2013. 1. 8.
% Copyright (c) pkim _AT_ scripts.pe.kr
%}


function y = arcsinh(x)
    y = log(x + sqrt(x*x + 1));
endfunction


function y = arccosh(x)
    y = log(x + sqrt(x*x - 1));
endfunction


x = -0.9;
y = asin(x);

printf("y = asin(%g) = %.9f\n", x,  y);
printf("sin(y) = sin(%.9f) = %g\n", y, sin(y));
printf("\n");

x = 1.1;
u = acosh(x);
printf("u = acosh(%g) = %.10f\n", x,  u);

v = asinh(x);
printf("v = asinh(%g) = %.10f\n", x, v);

printf("cosh(u) = cosh(%.10f) = %g\n", u, cosh(u));
printf("sinh(v) = sinh(%.10f) = %g\n", v, sinh(v));
printf("\n");

printf("arccosh(%g) = %.10f\n", x, arccosh(x));
printf("arcsinh(%g) = %.10f\n", x, arcsinh(x));

#{
Output:
y = asin(-0.9) = -1.119769515
sin(y) = sin(-1.119769515) = -0.9

u = acosh(1.1) = 0.4435682544
v = asinh(1.1) = 0.9503469298
cosh(u) = cosh(0.4435682544) = 1.1
sinh(v) = sinh(0.9503469298) = 1.1

arccosh(1.1) = 0.4435682544
arcsinh(1.1) = 0.9503469298

#}

 

 

 

Posted by Scripter
,

역삼각함수란 삼각함수의 역함수를 의미하고,

역쌍곡선함수란 쌍곡선함수의 역함수를 의미한다.

수학에서 sin 함수의 역함수는 arcsin 으로 표기되는데,

Boo 언어에서는 닷넷에서 사용하는  Math.Asin() 함수를 쓰면 된다.

이를 사용하기 위해서는 import 구문

import System

이 필요하다.

 

Boo 언어는 Pytyhon 언어와 비슷하며, 닷넷 용이라는 점에서는 IronPython 과 더더욱 비슷하다.

다음 소스는 Boo 인타프리터 booi 로 실행해도 되고, Boo 컴파일러 booc 로 컴파일하여 생성된 실행 파일을 실행해도 된다. booc 로 컴파일이 성공적으로 끝나면 *.exe 파일과 *.pdb 파일이 생성된다.

#  Filename: testArcSine.boo
#
#   Execute: booi testArcSine.boo
#
#    Or
#
#   Compile: booc testArcSine.boo
#   Execute: testArcSine.boo
#
# Date: 2013. 1. 6.
# Copyright (c) pkim _AT_ scripts.pe.kr

import System

def asinh(x as double) as double:
    y = Math.Log(x + Math.Sqrt(x*x + 1))
    return y

def acosh(x as double) as double:
    y = Math.Log(x + Math.Sqrt(x*x - 1))
    return y


# 실행 시작 지점
x = -0.9
y = Math.Asin(x)
print string.Format("y = asin({0}) = {1:F9}", x,  y)
print string.Format("sin(y) = sin({0:F9}) = {1}", y, Math.Sin(y))
print

x = 1.1
u = acosh(x)
print string.Format("u = acosh({0}) = {1:F10}", x,  u)

v = asinh(x)
print string.Format("v = asinh({0}) = {1:F10}", x,  v)

print string.Format("cosh(u) = cosh({0:F10}) = {1}", u,  Math.Cosh(u))
print string.Format("sinh(v) = sinh({0:F10}) = {1}", v,  Math.Sinh(v))

/*
Output:
y = asin(-0.9) = -1.119769515
sin(y) = sin(-1.119769515) = -0.9

u = acosh(1.1) = 0.4435682544
v = asinh(1.1) = 0.9503469298
cosh(u) = cosh(0.4435682544) = 1.1
sinh(v) = sinh(0.9503469298) = 1.1
*/

 

 

Posted by Scripter
,