정수부의 자리수가 조금 큰 부동소수점수(64비트 double 포맷의 수)를 십진수 표현으로 출력해 보았습니다.

십진수로 표현하면  유효자리수 개수가 약 14~15개 정도인데,

Java 언어와 C# 언어에서는 유효수자 개수로 자르고 그 뒤를 모두 0으로 출력지만,

Ruby 언어에서는 Python, C/C++ 언어들 처럼 유효수자 아래 부분을 자르지 않고 모두 츨력합니다.

 

물론 Java, C#, Python, C, C++ 어느 프로그램 언어든

십진수로 표현할 때 자르는 방법이나 유효수자 아래 부분을 채우는 방법은 다르지만,

덧셈, 뺄셈, 곱셈, 나누셈, 기타 등등에서 유효수자 아래부분의 처리 결과는 대동소이합니다.

 

 

 

# -*- coding: utf-8 -*-
#
# Filename: Test_Of_Native_Double_Precison_01.rb
#
#
# Execute: ruby Test_Of_Native_Double_Precison_01.rb
# Output:
#            2.pow(128) = 340282366920938463463374607431768211456.000000
#            2.pow(128) = 340282366920938463463374607431768211456
#                2**128 = 340282366920938463463374607431768211456
#         2**64 * 2**64 = 340282366920938463463374607431768211456
#
#
#  ------------------------------------------------------
#  출처: https://scripting.tistory.com/
#  ------------------------------------------------------


def test_01()
    y = 2.pow(128)
    print("       2.pow(128) = %f\n" % y)
    print("       2.pow(128) = %.f\n"% y)

    z = 2**128
    print("           2**128 = %d\n" % z)
    print("    2**64 * 2**64 = %d\n" % (2**64 * 2**64))
end
    

test_01()
print

 

 

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 )

 

Ruby 언어에는 지수 연산자 ** 를 (밑수)**(지수) 의 형식으로 언어 자체에서 지원하고 있다. 하지만 차후 필요한 데가 있을 것 같아서 이와 유사한 n 제곱 함수와 n 제곱근 함수를 구현해 보았다.

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

아래의 소스는 대부분 버전의 Ruby 에서 실행되도록 작성된 소스이다.

참고로, Ruby 언어는 (다른 언어와 달리) 대분자만으로 쓰여진 것은 구문상 변수가 아니라 상수를 의미한다. 잠간 irb(인터랙티브 Ruby)를 실행하여 확인해 보자.

irb(main):001:0> ABC = 5
=> 5
irb(main):002:0> ABC = 3
(irb):2: warning: already initialized constant ABC
=> 3

그러므로 아래의 소스 첫 부분에

MAX_ITER = 20000
M_EPSILON = 1.0e-15

로 선언한 것은 (두 전역변수가 아니라) 두 상수를 선언한 것이며, 이는 소스 전체에서 통용된다.

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

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

MAX_ITER = 20000
M_EPSILON = 1.0e-15

#
# Compute the n-th root of x to a given scale, x > 0.
#
def nPow(a, n)
    if n > 0
        if n == 1
            return a
        else
            if a == 0.0 or a == 1.0
                return a
            elsif a == -1.0
                if n % 2 == 1
                    return -1.0
                else
                    return 1.0
                end
            elsif a < 0.0
                if n % 2 == 1
                    return -nPow(-a, n)
                else
                    return nPow(-a, n)
                end
            else
                y = 1.0
                for i in 0...n do
                    y *= a
                end
                return y
            end
         end
    elsif n == 0
        return 1.0
    else      #  when n < 0
        if a == 0.0
            raise RuntimeError,'Negative powering exception of zero.'
        else
            if n == -1
                return 1.0/a
            else
                return 1.0/nPow(a, -n)
            end
        end
    end
end


#
# Compute the n-th root of x to a given scale, x > 0.
#
def gPow(a, n)
    if n > 0
        if n == 1
            return a
        else
            if a == 0.0 or a == 1.0
                return a
            elsif a == -1.0
                if n % 2 == 1
                    return -1.0
                else
                    return 1.0
                end
            elsif a < 0.0
                if n % 2 == 1
                    return -gPow(-a, n)
                else
                    return gPow(-a, n)
                end
            else
                y = 1.0
                r = a
                m = 8*4 - 1            #  8*sizeof(int) - 1;
                one = 1
                for i in 0..m do
                    if (n & one) == 0
                        y *= 1.0
                    else
                        y *= r
                    end
                    r = r*r
                    one <<= 1
                    if one > n
                        break
                    end
                end
                return y
            end
        end
    elsif n == 0
        return 1.0
    else      #  when n < 0
        if a == 0.0
            raise RuntimeError,'Negative powering exception of zero.'
        else
            if n == -1
                return 1.0/a
            else
                return 1.0/gPow(a, -n)
            end
        end
    end
end

 

#
# Compute the n-th root of x to a given scale, x > 0.
#
def mPow(a, n)
    if n > 0
        if n == 1
            return a
        else
            if a == 0.0 or a == 1.0
                return a
            elsif a == -1.0
                if n % 2 == 1
                    return -1.0
                else
                    return 1.0
                end
            elsif a < 0.0
                if n % 2 == 1
                    return -mPow(-a, n)
                else
                    return mPow(-a, n)
                end
            else
                y = 1.0
                r = a
                m = n
                while m > 0 do
                    if (m & 0x1) == 1
                        y *= r
                    end
                    r = r*r
                    m >>= 1
                end
                return y
            end
        end
    elsif n == 0
        return 1.0
    else      #  when n < 0
        if a == 0.0
            raise RuntimeError,'Negative powering exception of zero.'
        else
            if n == -1
                return 1.0/a
            else
                return 1.0/mPow(a, -n)
            end
        end
    end
end


#
# Compute the square root of x to a given scale, x > 0.
#
def heronSqrt(a)
    if a < 0.0
        raise RuntimeError,'Cannot find the sqrt of a negative number.'
    elsif a == 0.0 or a == 1.0
        return a
    else
        x1 = a
        x2 = (x1 + a/x1)/2.0
        er = x1 - x2
        counter = 0
        while x1 + er != x1 do
            x1 = x2
            x2 = (x1 + a/x1)/2.0
            er = x1 - x2
            if (er).abs < (M_EPSILON*x1).abs
                break
            end
            counter += 1
            if counter > MAX_ITER
                break
            end
        end
        if counter >= MAX_ITER
            raise RuntimeError,'Inaccurate sqrt exception by too many iterations.'
        end
        return x2
    end
end


#
# Compute the cubic root of x to a given scale, x > 0.
#
def newtonCbrt(a)
    if a == 0.0 or a == 1.0 or a == -1.0
        return a
    elsif a < 0.0
        return -newtonCbrt(-a)
    else
        x1 = a
        x2 = (2.0*x1 + a/(x1*x1))/3.0
        er = x1 - x2
        counter = 0
        while x1 + er != x1 do
            x1 = x2
            x2 = (2.0*x1 + a/(x1*x1))/3.0
            er = x1 - x2
            if (er).abs < (M_EPSILON*x1).abs
                break
            end
            counter += 1
            if counter > MAX_ITER
                break
            end
        end
        if counter >= MAX_ITER
            raise Error,'Inaccurate sqrt exception by too many iterations.'
        end
        return x2
    end
end


#
# Compute the n-th root of x to a given scale, x > 0.
#
def newtonNthRoot(n, a)
    if n == 0
        return 1.0
    elsif n == 1
        return a
    elsif n > 0
        if a == 0.0 or a == 1.0
            return a
        elsif a == -1.0
            if n % 2 == 1
                return a
            else
                raise RuntimeError,'Cannot find the even n-th root of a negative number.'
            end
        elsif a < 0.0
            if n % 2 == 1
                return -newtonNthRoot(n, -a)
            else
                raise RuntimeError,'Cannot find the even n-th root of a negative number.'
            end
        elsif a < 1.0
            return 1.0/newtonNthRoot(n, 1.0/a)
        else
            x1 = a
            xn = mPow(x1, n - 1)
            x2 = ((n -1)*x1 + a/xn)/n
            er = x1 - x2
            counter = 0
            while x1 + er != x1 do
                x1 = x2
                xn = mPow(x1, n - 1)
                x2 = ((n -1)*x1 + a/xn)/n
                er = x1 - x2
                if (er).abs < (M_EPSILON*x1).abs
                    break
                end
                counter += 1
                if counter > MAX_ITER
                    break
                end
            end
            if counter >= MAX_ITER
                raise RuntimeError, 'Inaccurate sqrt exception by too many iterations.'
            end
            return x2
        end
    else
        if a == 0.0
            raise Error, 'Cannot find the negative n-th root of zero.'
        else
            return 1.0/newtonNthRoot(-n, a)
        end
    end
end 


x = 16.0
u = Math.sqrt(x)

print "[ Testing heronSqrt(double) ]--------------------\n"
print "x = %g\n" % x
print "u = sqrt(%g) = %g\n" % [x, u]
y = heronSqrt(x)
print "y = heronSqrt(%g) = %g\n" % [x, y]
print "y*y = %g\n" % (y*y)
print "\n"

print "[ Testing newtonCbrt(double) ]--------------------\n"
x = -216.0
print "x = %g\n" % x
print "-exp(log(-x)/3.0) = %g\n" % -Math::exp(Math::log(-x)/3.0)
w = newtonCbrt(x)
print "w = newtonCbrt(%g) = %g\n" % [x, w]
print "w*w*w = %g\n" % (w*w*w)
print "\n"

x = 729000000000.0
print "x = %g\n" % x
print "exp(log(x)/3.0) = %g\n" % Math::exp(Math::log(x)/3.0)
w = newtonCbrt(x)
print "w = newtonCbrt(%g) = %g\n" % [x, w]
print "w*w*w = %g\n" % (w*w*w)
print "\n"

print "[ Testing newtonNthRoot(int, double) ]--------------------\n"
z = newtonNthRoot(3, x)
print "x = %g\n" % x
print "z = newtonNthRoot(3, %g) = %g\n" % [x, z]
print "z*z*z = %g\n" % (z*z*z)
print "\n"

x = 12960000000000000000.0
z = newtonNthRoot(4, x)
print "x = %g\n" % x
print "z = newtonNthRoot(4, x) = newtonNthRoot(4, %g) =  %g\n" % [x, z]
print "z*z*z*z = %g\n" % (z*z*z*z)
print "\n"

x = 1.0/12960000000000000000.0
z = newtonNthRoot(4, x)
print "x = %g\n" % x
print "exp(log(x)/4.0) = %g\n" % Math::exp(Math::log(x)/4.0)
print "z = newtonNthRoot(4, x) = newtonNthRoot(4, %g) =  %g\n" % [x, z]
print "z*z*z*z = %g\n" % (z*z*z*z)
print "\n"


begin
    x = -4.0
    print "[ Test Exception heronSqrt(double) ]--------------------\n"
    print "x = %g\n" % x
    print "Calculating heronSqrt(%g)\n" % x
    y = heronSqrt(x)
    print "y = heronSqrt(%g) = %g\n" % [x, y]
    print "y*y = %g\n" % (y*y)
    print "\n"
rescue RuntimeError => ex
    print "%s\nCaught some exception in calculating heronSqrt(%g)\n" % [ex, x]
    print "\n"
end


begin
    x = -4.0
    print "[ Test Exception in newtonCbrt(double) ]--------------------\n"
    print "x = %g\n" % x
    print "Calculating newtonCbrt(%g)\n" % x
    y = newtonCbrt(x)
    print "y = newtonCbrt(%g) = %g\n" % [x, y]
    print "y*y*y = %g\n" % (y*y*y)
    print "\n"
rescue RuntimeError => ex
    print "%s\nCaught some exception in calculating newtonCbrtrt(%g)\n" % [ex, x]
    print "\n"
end


print "[ Test calculations by powering ]-----------------------------\n"
x = 200.0
z = newtonNthRoot(10, x)
print "x = %g\n" % x
print "exp(log(x)/10.0) = %g\n" % Math::exp(Math::log(x)/10.0)
print "z = newtonNthRoot(10, x) = newtonNthRoot(10, %g) = %g\n" % [x, z]
print "pow(z, 10) = %g\n" % z**10
print "\n"

x = 3001.0
z = newtonNthRoot(99, x)
print "x = %g\n" % x
print "exp(log(x)/99.0) = %g\n" % Math::exp(Math::log(x)/99.0)
print "z = newtonNthRoot(99, x) = newtonNthRoot(99, %g) = %g\n" % [x, z]
print "pow(z, 99) = %g\n" % z**99
print "\n"

x = 3001.0
z = newtonNthRoot(-99, x)
print "x = %g\n" % x
print "exp(log(x)/-99.0) = %g\n" % Math::exp(Math::log(x)/-99.0)
print "z = newtonNthRoot(-99, x) = newtonNthRoot(-99, %g) = %g\n" % [x, z]
print "1.0/pow(z, 99) = %g\n" % (1.0/z**99)
print "\n"

print "2.1**2.1 = pow(2.1, 2.1) = %g\n" % 2.1**2.1
print "2.1**(-2.1) = pow(2.1, -2.1) = %g\n" % 2.1**(-2.1)
print "2.1**2.1 * 2.1**(-2.1) = pow(2.1, 2.1) * pow(2.1, -2.1) = %g\n" % ((2.1** 2.1)*2.1**( -2.1))
print "2.1**2.1 = exp(2.1*log(2.1)) = %g\n" % Math::exp(2.1*Math::log(2.1))
print "2.1**(-2.1) = exp(-2.1*log(2.1)) = %g\n" % Math::exp(-2.1*Math::log(2.1))
print "2.1**2.1 * 2.1**(-2.1) = exp(2.1*log(2.1)) * exp(-2.1*log(2.1)) = %g\n" % (Math::exp(2.1*Math::log(2.1)) * Math::exp(-2.1*Math::log(2.1)))
print "\n"


k = 301
x = -1.029
t1 = nPow(x, k)
t2 = gPow(x, k)
t3 = mPow(x, k)
print "math.pow(%g, %d) = %g\n" % [x, k,  x**k ]   # pow(x, k)
print "t1 = nPow(%g, %d) = %g\n" % [x, k,  t1]
print "t2 = gPow(%g, %d) = %g\n" % [x, k,  t2]
print "t3 = mPow(%g, %d) = %g\n" % [x, k,  t3]
print "t1 / t2 = %g\n" % (t1 / t2)
print "t1 - t2 = %g\n" % (t1 - t2)
print "t1 == t2 ? "
if t1 == t2
    print "yes\n"
else
   print "no\n"
end
print "t1 / t3 = %g\n" % (t1 / t3)
print "t1 - t3 = %g\n" % (t1 - t3)
print "t1 == t3 ? "
if t1 == t3
    print "yes\n"
else
   print "no\n"
end
print "t2 / t3 = %g\n" % (t2 / t3)
print "t2 - t3 = %g\n" % (t2 - t3)
print "t2 == t3 ? "
if t2 == t3
    print "yes\n"
else
   print "no\n"
end
print "\n"

print "Done.\n"


=begin
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 = 7.29e+11
exp(log(x)/3.0) = 9000
w = newtonCbrt(7.29e+11) = 9000
w*w*w = 7.29e+11

[ Testing newtonNthRoot(int, double) ]--------------------
x = 7.29e+11
z = newtonNthRoot(3, 7.29e+11) = 9000
z*z*z = 7.29e+11

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

x = 7.71605e-20
exp(log(x)/4.0) = 1.66667e-05
z = newtonNthRoot(4, x) = newtonNthRoot(4, 7.71605e-20) =  1.66667e-05
z*z*z*z = 7.71605e-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.5874
y*y*y = -4

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

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

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

2.1**2.1 = pow(2.1, 2.1) = 4.74964
2.1**(-2.1) = pow(2.1, -2.1) = 0.210542
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.74964
2.1**(-2.1) = exp(-2.1*log(2.1)) = 0.210542
2.1**2.1 * 2.1**(-2.1) = exp(2.1*log(2.1)) * exp(-2.1*log(2.1)) = 1

math.pow(-1.029, 301) = -5457.93
t1 = nPow(-1.029, 301) = -5457.93
t2 = gPow(-1.029, 301) = -5457.93
t3 = mPow(-1.029, 301) = -5457.93
t1 / t2 = 1
t1 - t2 = 6.18456e-11
t1 == t2 ? no
t1 / t3 = 1
t1 - t3 = 6.18456e-11
t1 == t3 ? no
t2 / t3 = 1
t2 - t3 = 0
t2 == t3 ? yes

Done.
=end

 

 

 

Posted by Scripter
,

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

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

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

Ruby 언어에서는 Math::asin() 함수로 구현되어 있다.

 

다음 소스는 Ruby, JRuby 중 어느 것으로 실행해도 같은 결과를 얻는다.

 

# -*- encoding: utf-8 -*-

# Filename: testArcSine.rb
#
# Execute: ruby testArcSine.rb
#
#  Or
#
# Execute: jruby testArcSine.rb
#
# Date: 2013. 1. 1.
# Copyright (c) pkim _AT_ scripts.pe.kr

def sin(x)
    y = Math::sin(x)
    return y
end

def asin(x)
    y = Math::asin(x)
    return y
end

def sinh(x)
    y = Math::sinh(x)
    return y
end

def cosh(x)
    y = Math::cosh(x)
    return y
end

def asinh(x)
    y = Math::log(x + Math::sqrt(x*x + 1))
    return y
end

def acosh(x)
    y = Math::log(x + Math::sqrt(x*x - 1))
    return y
end


x = -0.9
y = asin(x)
print "y = asin(%.1g) = %.9f\n" % [x,  y]
print "sin(y) = sin(%.9f) = %.1g\n" % [y, sin(y)]
print "\n"

x = 1.1
u = acosh(x)
print "u = acosh(%3.2g) = %.10f\n" % [x,  u]

v = asinh(x)
print "v = asinh(%3.2g) = %.10f\n" % [x,  v]

print "cosh(u) = cosh(%.10f) = %3.2g\n" % [u,  cosh(u)]
print "sinh(v) = sinh(%.10f) = %3.2g\n" % [v,  sinh(v)]

=begin
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
=end

 

 

Posted by Scripter
,

* 아래는 높은 버전(1.9.2 이상)의 Ruby를 사용할 때 적용된다.

UTF--8 인코딩이면 영문이든 한글이든 모두 문자열을 거꾸로 하기가 잘된다.

String.reverse 또는 Strig.reverse() 하면 거꾸로 된 문자열을 얻는다.


예제 1.  UTF-8 한글 문자열을 잘 처리하는 예제

# -*- encoding: utf-8 -*-

a = "Hello, world!"
b = "안녕하세요? 아햏햏"
puts "%s --> %s" % [a, a.reverse()]
puts "%s --> %s" % [b, b.reverse()]
####################
# Expected:
#   Hello, world! --> !dlrow ,olleH
#   안녕하세요? 아햏햏 --> 햏햏아 ?요세하녕안
# Result:
#   Hello, world! --> !dlrow ,olleH
#   안녕하세요? 아햏햏 --> 햏햏아 ?요세하녕안
####################



버전 1.8.6 이하의 Ruby 언어에서는 유니코드를 거의 지원하지 않아서 iconv 를 이용하여 문자열 인코딩 변환을 하였지만. 버전 1.9.2 이상의 Ruby 언어에서는 유니코드를 지원하므로 reverse 뿐만 아니라 split를 써도 된다.

다음은 reverse 대신 split를 적용하여 한글은 거꾸로 하는 에제이다.


예제 2. 높은 버전의 Ruby 언어에서 UTF-8 한글 문자열을 분리하여 거꾸로 하는 예제

# -*- encoding: utf-8 -*-

a = "Hello, world!"
b = "안녕하세요? 아햏햏"

# 루비 언어에서 문자열 분리하여 거꾸로 하기
for i in b.split(//u).reverse do
    print "%s<br />\n" % i
end
for i in b.upcase.gsub(/([ㄱ-ㅎㅏ-ㅣ가-힣])/u,'\1.').split('.').reverse do
    print "%s<br />\n" % i
end

####################
# Expected:
# 햏<br />
# 햏<br />
# 아<br />
#  <br />
# ?<br />
# 요<br />
# 세<br />
# 하<br />
# 녕<br />
# 안<br />
# 햏<br />
# 햏<br />
# ? 아<br />
# 요<br />
# 세<br />
# 하<br />
# 녕<br />
# 안<br />
# Result:
# 햏<br />
# 햏<br />
# 아<br />
#  <br />
# ?<br />
# 요<br />
# 세<br />
# 하<br />
# 녕<br />
# 안<br />
# 햏<br />
# 햏<br />
# ? 아<br />
# 요<br />
# 세<br />
# 하<br />
# 녕<br />
# 안<br />
####################




Posted by Scripter
,

Mac OS X Lion 에서 Ruby 1.9.2  에서 Tk GUI 사용하려면 ActiveTcl 을 먼저 설치하는 것이 좋다.
(만약 Ruby 1.9.2 가 설치되어 있다면 Tk 를 살치한 후 Ruby  를 재컴파일 & 재설치하면 된다.)

1. Mac OS X 용 ActiveTcl 8.5 다운로드

2. Mac OS X 용 Ruby 다운로드 
    * 또는 1.9 안정화 버젼: Ruby 1.9.2-p290(tar.bz2 | tar.gz | zip)
      (참고: http://www.ruby-lang.org/ko/downloads/)

3. ActiveTcl 8.5 설치하기
다운로드된  Active 8.5.10 의 mpkg 파일을 클릭하면 나타나는 다음 창에서 ActiveTcl-8.5.pkg 의 아이콘을 더블클릭하면 설치된다.




4. Ruby 1.9.2 설치하기
Ruby 1.9.2  의 압축이 해제된 기본 폴더(top folder)로 가서 다음 명령을 내린다.
(참고: http://blog.jeffdouglas.com/2011/08/01/ruby-1-9-2-install-errors-with-mac-os-x-lion-and-rvm/)
(아래에서 <install-dir> 부분은 자신의 시스템 환경에 알맞는 폴더명을 적어준다. 보통은 /usr/local/bin 이다.)

$ ./configure   --prefix=<install-dir>
                       --with-tcltk-framework=/Library/Frameworks
                       --enable-pthread
                       --enable-shared
$ make 

$ sudo make install


5. 첫쨰 Tk GUI 예제 (소스파일명: helloRuby.rb)
require 'tk'
require 'tkextlib/tile'
root = TkRoot.new() 
button = Tk::Tile::TButton.new(root) {text "Hello World"}.grid
Tk.mainloop()



6. 실행하기
$ ruby1.9 helloRuby.rb

7. 실행 결과:


8. 한글 테스트를 위한 둘쨰 Tk GUI 예제 (소스파일명: helloRubyTk.rb)

# coding : utf-8


require 'tk'

require 'tkextlib/tile'

root = TkRoot.new() 

button = Tk::Tile::TButton.new(root) {text "Hello, world!\n안녕하세요?\n한글이 잘 되나 봅시다."}.grid

Tk.mainloop()
 



9. 실행하기
ruby1.9 hellozRuby.rb

10. 실행 결과: 



Posted by Scripter
,

Ruby 언어로 숫자 맞추기 게임을 작성해 보았다.
Python 언어의 input()  함수에 대응하는 함수로서 사용자가 컨솔에서 입력한 것을 스트링으로 받는 Ruby 언어의 함수는 gets()이다. 그런데 Ruby 언어의 간편 구문표기(syntax sugar)에 따라 소괄호 열기와 닫기를 생략하여 gets만 해도 된다. 즉 아래 소스의 14째 줄 
               sbuf = gets

               sbuf = gets()
의 간편 구문표기(syntax sugar)이다.

아래 소스의 15째 줄 guess = sbuf.to_i 는 스트링을 정수로 타입변환하는 과정이다.



소스 파일명: guessNumber01.rb

  1. #!/env/ruby
  2. #
  3. #   Filename: guessNumber01.rb
  4. #   Purpose:  Interatice game guessing a given number.
  5. #                 if CONDITION
  6. #                     ......
  7. #                 else
  8. #                     ......
  9. #                 end
  10. #   Execute: ruby guessNumber01.rb
  11. def doGuessing(num)
  12.     puts("Enter your guess:")
  13.     sbuf = gets
  14.     guess = sbuf.to_i
  15.     if guess == num
  16.         puts("You win!")
  17.         return
  18.     end
  19.     # we won't get here if guess == num
  20.     if guess < num
  21.         puts("Too low!")
  22.         doGuessing(num)
  23.     else
  24.         puts("Too high!")
  25.         doGuessing(num)
  26.     end
  27. end
  28. doGuessing(123)




실행> ruby guessNumber01.rb
Enter your guess:
111
Too low!
Enter your guess:
222
Too high!
Enter your guess:
123
You win!



위의 소스는 JRuby 1.1.6으로 실행해도 똑같이 실행된다.

실행> jruby guessNumber01.rb
Enter your guess:
111
Too low!
Enter your guess:
222
Too high!
Enter your guess:
123
You win!




Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.




Posted by Scripter
,


[파일명:  testStringFindInList.rb]------------------------------------------------
def find(arr, s)
    for i in 0..arr.size() do
     if arr[i].index(s) != nil
      return i
        end
    end
    return -1;
end

def printArray(arr)
    print("[")
    for i in 0..arr.size() - 1 do
         print(arr[i] + ", ")
    end
    if arr.size() > 0
        print(arr[arr.size() - 1])
    end
    print("]\n")
end

words = ["하나", "둘", "셋", "넷", "다섯", "여섯"]

print("list: ")
printArray(words)
where = find(words, "셋")
if where > 0
    print("발견!  ")
    print("Next word of 셋 in list: " + words[where+1] + "\n")
end

print("Sorting..." + "\n")
words = words.sort()

print("list: ")
printArray(words)
where = find(words, "셋")
if where > 0
    print("발견!  ")
    print("Next word of 셋 in list: " + words[where+1] + "\n")
end
------------------------------------------------


실행> ruby testStringFindInList.rb
list: [하나, 둘, 셋, 넷, 다섯, 여섯]
발견!  Next word of 셋 in list: 넷
Sorting...
list: [넷, 다섯, 둘, 셋, 여섯, 하나]
발견!  Next word of 셋 in list: 여섯



크리에이티브 커먼즈 라이선스
Creative Commons License

Posted by Scripter
,


[파일명:  testSort.rb]------------------------------------------------
def printArray(a)
    for i in a do
        print i + ", "
    end
    print "\n"
end

list = ARGV.sort()
printArray(list)
------------------------------------------------


실행> ruby testSort.rb 자전차 자전거 전동차 전차 전기자동차
자전거, 자전차, 전기자동차, 전동차, 전차,



 

크리에이티브 커먼즈 라이선스
Creative Commons License

 

Posted by Scripter
,


정의 (소수와 합성수)
    1보다 큰 양의 정수 n에 대하여
    (i) n = a * b 를 만족하고 1보다 큰 두 양의 정수 a와 b가 존재하면,
        n을 합성수(合成數, composite number)라고 한다. 참고로 이 경우,
        a, b 중에 적어도 하나는 sqrt(n) 보다 작거나 같다.
        합성수의 예로는 4, 6, 9, 24, 143 등이 있다.
    (ii) n = a * b 를 만족하고 1보다 큰 두 양의 정수 a와 b가 존재하지 않으면,
         즉 n을 두 양의 정수의 곱으로 표현하는 방법이 1*n과 n*1 두 가지 뿐이면,
         n을 소수(素數, prime number)라고 한다.  소수의 예로는 2, 3, 5, 7, 11 등이 있다.
         n이 소수인지 아닌지 확인하려면, 
         n을 2 보다 크거나 같고 sqrt(n) 보다 작거나 같은 모든 정수로 나누어 본다.
         이 경우 언제나 나누어 떨어지지  않으면 n은 소수이고, 그렇지 않으면 n은 합성수이다.
    

우선 다음의 Ruby 소스 코드는 명령행 인자로 전달 받은 양의 정수 n을
2 및 3, 5, 7, ... , sqrt(n) 이하의 홀수들로 나누어 보아 n이 합성수인지 아닌지
확인하는 애플리케이션 소스이다. 확인하는데 걸린 경과 시간도 알려준다.


#  Filename: divideEach.rb
#
#  Purpose:  Determine whether the given integer is a prime or not.
#
#  Execute: ruby divideEach.rb [integer]
#
#     Date:  2009/03/23
#   Author:  PH Kim   [ pkim ((AT)) scripts.pe.kr ]

=begin
  Execution Examples:

      Prompt> ruby divideEach.rb 1234567812343
      1234567812343 = 1 * 1234567812343
      1234567812343 is a prime
      Elapsed time: 2.875000 sec
 
      Prompt> ruby divideEach.rb 9999994200000841
      9999994200000841 = 99999971 * 99999971
      9999994200000841 is a not prime
      Elapsed time: 258.906000 sec

      Prompt> ruby divideEach.rb 18446744073709551617
      18446744073709551617 = 274177 * 67280421310721
      18446744073709551617 is a not prime
      Elapsed time: 0.766000 sec

      Prompt> ruby divideEach.rb 10023859281455311421
      10023859281455311421 = 1308520867 * 7660450463
      10023859281455311421 is a not prime
      Elapsed time: 3521.562000 sec
=end

n = 10006099720301
if ARGV.length > 0:
    n = ARGV[0].to_i
end

z = n / 2
if n == 2*z
    print "%d = %d * %d\n" % [n, 2, z]
end

time1 = Time.now.to_f

d = 1
k = 3
while k*k <= n
    z = n / k
    if n == k*z
        d = k
        break
    end
    k = k + 2
end

time2 = Time.now.to_f

print "%d = %d * %d\n" % [n, d, n/d]
if d == 1
    print "%d is a prime\n" % n
else
    print "%d is a not prime\n" % n
end

print "Elapsed time: %f sec\n" % (time2 - time1)




이제 다음은 정수의 인수분해 능력이 뛰어난  Pollard의 rho 방법(일명 거북이와 토끼 알고리즘, tortoise-hair algorithm)을 구현한  Ruby 소스 코드이다. 이 알고리즘은 소수에 대해서는 시간이 많이 걸리지만, 합성수에 대해서는 시간이 매우 적게 걸린다는 것이 특징이다.


#  Filename: pollardRho.rb
#
#  Purpose:  By using the pollard rho method,
#            determine whether the given integer is a prime or not.
#
#      See:  http://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm
#            http://en.wikipedia.org/wiki/Floyd%27s_cycle-finding_algorithm#Tortoise_and_hare#
#
#  Execute: ruby pollardRho.rb [integer]
#
#     Date:  2009/03/23
#   Author:  PH Kim   [ pkim ((AT)) scripts.pe.kr ]

=begin
  Execution Examples:

      Prompt> ruby pollardRho.rb 1234567812343
      Try first the Pollard rho algorithm with c = 2
      d = 1234567812343, count = 466951
      Try second the Pollard rho algorithm with c = 3
      d = 1, count = 1111112
      Try third the Pollard rho algorithm with c = 1
      d = 1234567812343, count = 799441
      1234567812343 = 1234567812343 * 1
      Elapsed time: 104.188000

      Prompt> ruby pollardRho.rb 9999994200000841
      Try first the Pollard rho algorithm with c = 2
      d = 99999971, count = 3593
      9999994200000841 = 99999971 * 99999971
      Elapsed time: 0.234000

      Prompt> ruby pollardRho.rb 18446744073709551617
      Try first the Pollard rho algorithm with c = 2
      d = 274177, count = 1028
      18446744073709551617 = 274177 * 67280421310721
      Elapsed time: 0.078000

      Prompt> ruby pollardRho.rb 10023859281455311421
      Try first the Pollard rho algorithm with c = 2
      d = 1308520867, count = 20350
      10023859281455311421 = 1308520867 * 7660450463
      Elapsed time: 1.531000
=end


def f(x, c, n)
    return (x*x + c) % n
end

def g(x, c, n)
    return f(f(x, c, n), c, n)
end

def gcd(x, y)
    a = x.abs
    b = y.abs
    if b == 0
        return a
    end
    while b != 0
        t = a % b
       a = b
        b = t
    end
    return a
end

def pollardRho(n)
    c = 2
    x = 1
    y = 1
    d = 1
    savedX = x
    count = 0
    print("Try first the Pollard rho algorithm with c = %d\n" % c)
    while d == 1 and count*count <= n
        x = f(x, c, n)
        if x == savedX
         print("It is cyclic.  x = %d\n" % x)
         break
        end
        y = g(y, c, n)
        d = gcd((x - y).abs, n)
        count = count + 1
        # if count % 5000 == 0
        #  print("  count = %d\n" % count)
        # end
    end

    print("d = %d, count = %d\n" % [d, count])
    if d > 1 and d < n
        return d
    end

    c = 3
    x = 1
    y = 1
    d = 1
    savedX = x
    count = 0
    print("Try second the Pollard rho algorithm with c = %d\n" % c)
    while d == 1 and count*count <= n
        x = f(x, c, n)
        if x == savedX
         print("It is cyclic.  x = %d\n" % x)
         break
        end
        y = g(y, c, n)
        d = gcd((x - y).abs, n)
        count = count + 1
        # if count % 5000 == 0
        #  print("  : count = %d\n" % count)
        # end
    end
   
    print("d = %d, count = %d\n" % [d, count])
    if d > 1 and d < n
        return d
    end

    c = 1
    x = 1
    y = 1
    d = 1
    savedX = x
    count = 0
    print("Try third the Pollard rho algorithm with c = %d\n" % c)
    while d == 1 and count*count <= n
        x = f(x, c, n)
        if x == savedX
         print("It is cyclic.  x = %d\n" % x)
         break
        end
        y = g(y, c, n)
        d = gcd((x - y).abs, n)
        count = count + 1
        # if count % 5000 == 0
        #  print("  :: count = %d\n" % count)
        # end
    end
   
    print("d = %d, count = %d\n" % [d, count])

    return d
end


n = 9991
if ARGV.length > 0
    n = ARGV[0].to_i
end

time1 = Time.now.to_f

k = pollardRho(n)
z = n/k
# if n == k*z
    print("%d = %d * %d\n" % [n, k, z])
# end

time2 = Time.now.to_f
print("Elapsed time: %f\n" % (time2 - time1))

 
 

크리에이티브 커먼즈 라이선스
Creative Commons License

Posted by Scripter
,


초등학교 때 배우는 두 정수의 곱셈표를 만들어 주는 Ruby 소스이다.

# Filename: makeMultTable.rb
#
#     Print a multiplication table.
#
#     Execute: ruby makeMultTable.rb 230 5100
#
# Date: 2009/03/06
#
#

def printUsing()
    print "Using: ruby makeMultTable.rb [number1] [number2]\n"
    print "Print a multiplication table for the given two integers.\n"
end

def printMultTable(x, y)
    nx = x
    if nx < 0
        nx = -nx
    end
    ny = y
    if ny < 0
        ny = -ny
    end
    ntail1 = 0
    ntail2 = 0
    while (nx % 10 == 0)
        nx = nx / 10
        ntail1 = ntail1 + 1
    end
    while (ny % 10 == 0)
        ny = ny / 10
        ntail2 = ntail2 + 1
    end
    z = nx * ny
    strZ = "%d" % z
    strX = "%d" % nx
    strY = "%d" % ny
    n = strY.length
    zeros  = "0000000000000000000000000000000000000000"
    whites = "                                        "
    bars   = "----------------------------------------"
    loffset = "       "
    line4 = loffset + strZ
    line1 = loffset + whites[0 ... strZ.length - strX.length] + strX
    line2 = "   x ) " +  whites[0 ... strZ.length - strY.length] + strY
    line3 = "     --" +  bars[0 ... strZ.length]
    print line1 + zeros[0 ... ntail1] + "\n"
    print line2 + zeros[0 ... ntail2] + "\n"
    print line3 + "\n"
    if (strY.length > 1)
        for i in 0...strY.length
            y1 = strY[strY.length - i - 1 ... strY.length - i].to_i
            if (y1 != 0)
                strT = "%d" % (nx * y1)
                print loffset + whites[0 ... strZ.length - strT.length - i] + strT + "\n"
            end
        end
        print line3 + "\n"
    end
    print line4 + zeros[0 ... ntail1] + zeros[0 ... ntail2] + "\n"
end

if (ARGV.length >= 2)
    x = ARGV[0].to_i
    y = ARGV[1].to_i
    print "\n"
    printMultTable(x, y)
else
    printUsing()
end




실행> ruby makeMultTable.rb 230 5100
결과>

          230
   x )   5100
     ------
         23
       115
     ------
       1173000

 

크리에이티브 커먼즈 라이선스
Creative Commons License

 

Posted by Scripter
,