多倍長精度による計算     Last modified: Aug 11, 2005

目的

円周率(π)と指数(e)を計算する関数,ユーザが定義するクラスの print method,二項演算子の関数定義の応用など。

使用法

calc.pi(length)
calc.e(length)

引数

length   計算したい小数点以下の桁数

ソース

インストールは,以下の 1 行をコピーし,R コンソールにペーストする
source("http://aoki2.si.gunma-u.ac.jp/R/src/multibyte.R", encoding="euc-jp")

# 多倍長計算を行う
"%add%" <- function(ans, b)                          # 足し算の演算子 ans %add% b を行い結果を返す
{                                                       # ans, b は "multibyte" クラスの多倍長整数
        ans <- ans+b                                 # 各桁の足し算を行う
        for (i in length(ans):1) {                      # 各桁について下の桁から,
                if (ans[i] >= 10000000000) {            # 繰り上がり処理を行う
                        ans[i] <- ans[i]-10000000000
                        ans[i-1] <- ans[i-1]+1
                }
        }
        return(ans)                                     # 結果を返す
}
#
"%sub%" <- function(ans, b)                          # 引き算の演算子 ans %sub% b を行い結果を返す
{                                                       # ans, b は "multibyte" クラスの多倍長整数
        ans <- ans-b                                 # 各桁の引き算を行う
        for (i in length(ans):1) {                      # 各桁について下の桁から,
                if (ans[i] < 0) {                    # 繰り下がり処理を行う
                        ans[i] <- ans[i]+10000000000
                        ans[i-1] <- ans[i-1]-1
                }
        }
        return(ans)                                     # 結果を返す
}
#
"%div%" <- function(ans, n)                          # 割り算の演算子 ans %div% n を行い結果を返す
{                                                       # 注:n は "multibyte" クラスではなく普通の整数値
        r <- 0                                               # 剰余
        for (i in 1:length(ans)) {                      # 各桁について上の桁から,
                x <- ans[i]+r*10000000000            # より上の位での剰余を考慮した,被除算数
                ans[i] <- x%/%n                              # 割り算を行い結果を格納
                r <- x-n*ans[i]                              # 今回の剰余
        }
        return(ans)                                     # 結果を返す
}
#
calc.pi <- function(len)                             # πの計算例 小数点以下 len 桁まで求める
{
        len <- len %/% 10+3                          # "multibyte" クラスの多倍長整数の必要桁数
        pi <- a <- b <- numeric(len)                   # 多倍長変数の領域確保 pi <- a <- b <- 0
        a[1] <- 16*5                                 # a[1] が最上位桁(a は小数点以下の数値を格納)
        n <- 1                                               # 除数
        repeat {                                        # 十分な精度を持つまで繰り返し計算
                a <- a %div% 25                              # a <- a / 25
                b <- a %div% n                               # b <- a / n
                pi <- pi %add% b                     # pi <- pi + b
                n <- n+2                             # n <- n + 2
                a <- a %div% 25                              # a <- a / 25
                b <- a %div% n                               # b <- a / n
                pi <- pi %sub% b                     # pi <- pi - b
                n <- n+2                             # n <- n + 2
                if (sum(b) == 0) break                  # pi の値が変化しなくなったらループ終了
        }
        a <- b <- numeric(len)                            # 多倍長変数の領域確保 a <- b <- 0
        a[1] <- 4*239                                        # a <- 4*239
        n <- 1                                               # 除数
        repeat {                                        # 十分な精度を持つまで繰り返し計算
                a <- a %div% 57121                   # a <- a / 57121
                b <- a %div% n                               # b <- a / n
                pi <- pi %sub% b                     # pi <- pi - b
                n <- n+2                             # n <- +2
                a <- a %div% 57121                   # a <- a / 57121
                b <- a %div% n                               # b <- a / n
                pi <- pi %add% b                     # pi <- pi + b
                n <- n+2                             # n <- n + 2
                if (sum(b) == 0) break                  # pi の値が変化しなくなったらループ終了
        }
        class(pi) <- "multibyte"                     # "multibyte" クラスにする(プリント・メソッドを使うため)
        return(pi)                                      # 結果を返す
}
#
calc.e <- function(len)                                      # e の計算例 小数点以下 len 桁まで求める
{
        len <- len %/% 10+3                          # "multibyte" クラスの多倍長整数の必要桁数
        e <- t <- numeric(len)                            # 多倍長変数の領域確保 e <- t <- 0
        e[1] <- t[1] <- 1                         # e <- t <- 1
        i <- 0                                               # 除数
        repeat {                                        # 十分な精度を持つまで繰り返し計算
                i <- i+1                             # i = 1, 2, ...
                t <- t %div% i                               # t = 1 / i!
                if (sum(t) == 0) break                  # t が 0 になるまで
                e <- e %add% t                               # e <- e + t
        }
        class(e) <- "multibyte"                              # "multibyte" クラスにする(プリント・メソッドを使うため)
        return(e)                                       # 結果を返す
}
#
print.multibyte <- function(ans)                     # プリント・メソッド
{
        if (ans[1] == 3) {                              # πの計算結果
                cat("π = 3.\n")
        }
        else {                                          # e の計算結果
                cat("e = 2.\n")
        }
        for (i in 2:(length(ans)-2)) {                  # 小数点以下の答えを出力する(ちょっと冗長だが)
                out <- paste("0000000000", as.character(ans[i]), sep="")
                len <- nchar(out)
                cat(sprintf(" %10s", substring(out, len-9, len)))
                if ((i-1) %% 5 == 0) cat("\n")          # 1行に50桁ずつ出力する
        }
        cat("\n")
}


使用例

# πを1000桁計算

 > calc.pi(1000)
 π = 3.
  1415926535 8979323846 2643383279 5028841971 6939937510
  5820974944 5923078164 0628620899 8628034825 3421170679
  8214808651 3282306647 0938446095 5058223172 5359408128
  4811174502 8410270193 8521105559 6446229489 5493038196
  4428810975 6659334461 2847564823 3786783165 2712019091
  4564856692 3460348610 4543266482 1339360726 0249141273
  7245870066 0631558817 4881520920 9628292540 9171536436
  7892590360 0113305305 4882046652 1384146951 9415116094
  3305727036 5759591953 0921861173 8193261179 3105118548
  0744623799 6274956735 1885752724 8912279381 8301194912
  9833673362 4406566430 8602139494 6395224737 1907021798
  6094370277 0539217176 2931767523 8467481846 7669405132
  0005681271 4526356082 7785771342 7577896091 7363717872
  1468440901 2249534301 4654958537 1050792279 6892589235
  4201995611 2129021960 8640344181 5981362977 4771309960
  5187072113 4999999837 2978049951 0597317328 1609631859
  5024459455 3469083026 4252230825 3344685035 2619311881
  7101000313 7838752886 5875332083 8142061717 7669147303
  5982534904 2875546873 1159562863 8823537875 9375195778
  1857780532 1712268066 1300192787 6611195909 2164201989

# e を1000桁計算
> calc.e(1000)
 e = 2.
  7182818284 5904523536 0287471352 6624977572 4709369995
  9574966967 6277240766 3035354759 4571382178 5251664274
  2746639193 2003059921 8174135966 2904357290 0334295260
  5956307381 3232862794 3490763233 8298807531 9525101901
  1573834187 9307021540 8914993488 4167509244 7614606680
  8226480016 8477411853 7423454424 3710753907 7744992069
  5517027618 3860626133 1384583000 7520449338 2656029760
  6737113200 7093287091 2744374704 7230696977 2093101416
  9283681902 5515108657 4637721112 5238978442 5056953696
  7707854499 6996794686 4454905987 9316368892 3009879312
  7736178215 4249992295 7635148220 8269895193 6680331825
  2886939849 6465105820 9392398294 8879332036 2509443117
  3012381970 6841614039 7019837679 3206832823 7646480429
  5311802328 7825098194 5581530175 6717361332 0698112509
  9618188159 3041690351 5988885193 4580727386 6738589422
  8792284998 9208680582 5749279610 4841984443 6346324496
  8487560233 6248270419 7862320900 2160990235 3043699418
  4914631409 3431738143 6405462531 5209618369 0888707016
  7683964243 7814059271 4563549061 3031072085 1038375051
  0115747704 1718986106 8739696552 1267154688 9570350354


・ 直前のページへ戻る  ・ E-mail to Shigenobu AOKI

Made with Macintosh