| 大きな数値を計算する一般的な方法については「多倍長演算」
「多倍長整数」などで検索してみてください。無限精度の小数は原
理的に実現不可能なので出来ないと思った方が良いと思います。
(代替としては固定小数点や有理数として扱う方法があります)
ここで挙げたSRCコードについてということであれば、 以下にコ
メントを付けたものを示しておきます。それからいくつかバグも見
つかったので修正してあります。ただ、何分即席な実装ですので、
これでもかなり処理を端折って(&インチキな手を使って)います。
加算以外の処理はまた色々手を加える必要があるでしょう。また当
然ながら、このコードを利用するにあたっては無制限かつ無保証で
すので、その旨ご了承ください。
一応、 さらに別の選択肢としてはSRC自体に多倍長整数のサポー
トを求める方向性もありますが、あまり需要はなさそうですし、こ
こで挙げたように非常に処理が複雑かつ今のSRCでは内部的に実装
が難しそうなので、受け入れられる可能性は低いと思います。やは
り大きな数値を扱わない(扱わずに済むように設計する)のが一番
望ましいです。
UPSplit:
local src = Args(1)
local slen = Args(2)
local odd = slen mod 7
local odds = Left(src, odd)
src = Mid(src, odd + 1)
local lst i
for i = (slen \ 7 - 1) to 0 step -1
lst = "$(lst) $(Mid(src, i * 7 + 1, 7))"
next
return "$(lst) $(odds)"
# String UPPlus(String a, String b)
#
# 対応SRCバージョン: 2.2
# 非限定精度の加算。引数は自然数(正の整数)に限る。
# 16桁以上の値を表すには文字列として指定する必要が
# あることに注意。
# UPPlus("123456789123456789", 12)
#
# ここで7桁ごとに計算している意味は特にない。
# 加算ならば最大14桁ごとに計算してもよい。
UPPlus:
# 例文では以下の値が渡されたと仮定する
# a = 12345678909876543
# b = 1111111111
local a = Args(1)
local b = Args(2)
# 桁数が少なければ普通に加算して返す
local la = Len(a)
local lb = Len(b)
if la < 15 and lb < 15 then
return (a + b)
endif
# 7桁ごとに区切ってリストにする
# 下位桁の方がリスト前に来る
# a = "9876543 4567890 123"
# b = "1111111 111"
a = UPSplit(a, la)
b = UPSplit(b, lb)
local answer i temp shift n
# リストの要素ごとに加算
# ループ回数は a および b のリスト長の長いほうにあわせる
# Max(LLength(a), LLength(b)) = 3
for i = 1 to Max(LLength(a), LLength(b))
# a と b の1要素、および桁上がり分を足す
# i = 1
# temp = 9876543 + 1111111 + 0 = 10876543
temp = LIndex(a, i) + LIndex(b, i) + shift
# 計算後の桁数
# n = 8
n = Len(temp)
# 桁数が8以上なら桁上がりとマークし、
# tempを7桁にする
# shift = 1
# temp = 0876543
if n > 7 then
shift = 1
temp = Right(temp, 7)
else
# 桁上がりが無いならshiftをリセット
shift = 0
# 7桁に満たないなら、
# 桁がずれないように先頭を0で埋める
if n < 7 then
temp = Format(temp, "0000000")
endif
endif
# 計算結果の先頭に付加
answer = "$(temp)$(answer)"
next
# 桁上がり分が残っていれば先頭に付加
if shift then
answer = "$(shift)$(answer)"
endif
# 先頭の連続した0を削除
answer = RegExpReplace(answer, "^0*", "")
# 空なら0に置き換える
if answer = "" then
answer = 0
endif
# answer = 12345680020987654
return answer
|