VBA技術解説
LSetとユーザー定義型のコピー(100桁の足し算)

ExcelマクロVBAの問題点と解決策、VBAの技術的解説
最終更新日:2020-07-09

LSetとユーザー定義型のコピー(100桁の足し算)


数の単位に「無量大数」というものがあります。
その桁数は10^68(10^88とする場合もあるよう)です。
VBAでこの無量大数の足し算をするにはどうしたら良いでしょうか。


方法としては、VBAで計算できる桁数にちぎって足し上げていけば良いでしょう。
ここではサンプルとして、100桁の数値を1桁ずつ足し上げていくVBAを紹介します。
そして、このサンプルVBAの中で、
RSetステートメント
LSetステートメント
Typeステートメント
LSetでユーザー定義型のコピー
これらを使用しています。

数値データ型の数値範囲



データ型 名称 格納できる範囲
Integer 整数型 -32,768 ~ 32,767
Long 長整数型 -2,147,483,648 ~ 2,147,483,647
LongLong 64ビット符号付き数値 -9223372036854775808 ~ 9223372036854775807
※64ビットプラットフォームのみで有効な宣言型
Single 単精度浮動小数点数型 -3.402823E38 ~ -1.401298E-45(負の値)
1.401298E-45 ~ 3.402823E38(正の値)
Double 倍精度浮動小数点数型 -1.79769313486232E308 ~ -4.94065645841247E-324(負の値)
4.94065645841247E-324 ~ 1.79769313486232E308(正の値)
Currency 通貨型 -922,337,203,685,477.5808 ~ 922,337,203,685,477.00
Decimal 10進数データ型 スケールが0 (小数部がない) の場合の利用可能な最大値は、 +/-79,228,162,514,264,337,593,543,950,335 になります。
小数点以下の桁数が28の場合、最大値は +/-ない場合、最小値0以外の値は、 +/-0.0000000000000000000000000001 です。

いずれにしても、整数値として正確に表すことのできる桁数は100桁には遠く及びません。

100桁数値の足し算VBA

Option Explicit

Const MaxDigits As Long = 100 '入力の最大桁数

Type tpA
  tpA1 As String * MaxDigits
End Type

Type tpB
  tpB1(1 To MaxDigits) As String * 1
End Type

'大きな文字列数値の足し算
Function AddBigNumber(ByVal arg1 As String, _
           ByVal arg2 As String) As String
  'LSetで構造体から構造体の配列にコピー
  Dim b1 As tpB, b2 As tpB
  LSet b1 = Str2Type(arg1)
  LSet b2 = Str2Type(arg2)
  
  '一桁ずつ足し上げていく
  Dim i As Long, tmp As String
  Dim ans(MaxDigits) As String 'インデックス0は桁上がり用
  For i = MaxDigits To 1 Step -1
    If Trim(b1.tpB1(i) & b2.tpB1(i)) = "" Then Exit For
    tmp = Str2Num(ans(i)) _
      + Str2Num(b1.tpB1(i)) + Str2Num(b2.tpB1(i))
    ans(i) = Right$(tmp, 1)
    ans(i - 1) = Left$(tmp, 1)
  Next
  
  AddBigNumber = Join(ans, "")
End Function

'文字列を構造体に入れて返す
Function Str2Type(ByVal str As String) As tpA
  RSet Str2Type.tpA1 = str
End Function

'文字列の数値化:スペースを0にする
Function Str2Num(ByVal str As String) As Long
  Str2Num = IIf(IsNumeric(str), str, 0)
End Function

100桁数値の足し算VBAの使い方と結果



Sub sample()
  Dim a1 As String, a2 As String
  a1 = "9999999999987654321098765432109876543210987654321098765432109876543210"
  a2 = "123456789012345678901234567890123456789012345678901234567890"
  Debug.Print AddBigNumber(a1, a2)
  
  a1 = "1"
  a2 = "99999999999999999999999999999999999999999999999999"
  Debug.Print AddBigNumber(a1, a2)
  
  a1 = "2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222"
  a2 = "8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888"
  Debug.Print AddBigNumber(a1, a2)
End Sub

イミディエイト ウィンドウに、
10000000000111111111111111111111111111111111111111111111111111111111100
100000000000000000000000000000000000000000000000000
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110

100桁数値の足し算VBAの解説

RSet ステートメント

文字列変数内の文字列を右揃えにします。

RSet 文字列変数 = 文字列

RSetは文字列変数の残りの文字を半角スペースに置き換えます。
文字列が文字列変数よりも長い場合、 RSetは左端から文字列変数の長さの文字だけを文字列変数に格納します。

LSet ステートメント

文字列変数内で文字列を左揃えにします。

RSet 文字列変数 = 文字列

LSetは文字列変数の残りの文字を半角スペースに置き換えます。
文字列が文字列変数よりも長い場合、 LSetは左端から文字列変数の長さの文字だけを文字列変数に格納します。

Type ステートメント

Typeステートメントは、ユーザー定義型の宣言です。

ユーザー定義型は、名前の通りユーザーが定義できるデータ型になります。
普通の変数は、1つの値しか入れられませんが、
ユーザー定義型は、複数の異なるデータ型を入れる事が出来ます。
プログラミング言語での一般的な呼び方としては、構造体とも呼ばれます。

Typeステートメントの詳細は以下を参照してください。
第110回.ユーザー定義型・構造体(Type)|VBA入門
ユーザー定義型は、名前の通りユーザーが定義できるデータ型になります。普通の変数は、1つの値しか入れられませんが、ユーザー定義型は、複数の異なるデータ型を入れる事が出来ます。プログラミング言語での一般的な呼び方としては、構造体とも呼ばれます。

ユーザー定義型変数のコピー:TypeとLSet

LSet ユーザー定義型変数1 = ユーザー定義型変数2

ユーザー定義型の変数を別の変数にコピーする場合、要素に指定されているデータ型は考慮されず、一方の変数のバイナリ データがもう一方の変数のメモリ領域にコピーされます。

MicrosoftのVBAリファレンスには、
LSet を使用してユーザー定義型の変数を別のユーザー定義型の変数にコピーすることはお勧めしません。
特定のデータ型用に予約されているスペースに別のデータ型のデータをコピーした場合、予期しない結果になることがあります。
このように書かれています。
今回は、これを承知の上でのサンプルVBAです。
以下は、桁数を少なくして見やすくした場合の例です。

Type tpA
  tpA1 As String * 5
End Type

Type tpB
  tpB1(4) As String * 1
End Type

Sub sample()
  Dim a As tpA
  Dim b As tpB
  RSet a.tpA1 = "123"
  LSet b = a
  Stop
End Sub

RSet a.tpA1 = "123"
a.tpA1に右寄せで"123"と入ります。

LSet b = a
5文字がString * 1の配列に入ります。

VBA マクロ 100桁数値 足し算 Type Lset RSet


上記VBAの参考ページ

第45回.VBA関数(Format)|VBA入門
VBAのFormat関数は、指定した書式に変換した文字列を返す関数で、ワークシート関数のTEXT関数とほぼ同様の機能になります。Format関数は、非常に使用頻度の高い関数でありマクロVBAにおいては重要かつ必須習得関数です。Format関数はしっかと使えるようにしておきましょう。
第106回.Functionプロシージャー|VBA入門
プログラム(マクロVBA)内で特定の作業を実行し値を返すプロシージャです。つまり、Functionプロシージャで独自の関数をつくれるということです。Subプロシードャーとの違いは、値を返すか返さないかの違いです。
第110回.ユーザー定義型・構造体(Type)|VBA入門
ユーザー定義型は、名前の通りユーザーが定義できるデータ型になります。普通の変数は、1つの値しか入れられませんが、ユーザー定義型は、複数の異なるデータ型を入れる事が出来ます。プログラミング言語での一般的な呼び方としては、構造体とも呼ばれます。
第113回.配列に関連する関数|VBA入門
マクロVBAで配列を使う上で、必要となるVBA関数がいくつかあります。より便利に配列を活用するために必須となるVBA関数、・LBound関数 ・UBound関数 ・Array関数 ・IsArray関数 ・Join関数 ・Filter関数 以上のVBA関数について解説します。
第133回.引数の数を可変にできるパラメーター配列(ParamArray)|VBA入門
Subプロシージャー、Functionプロシージャーにおいて、引数リストの数を特定せず、不定個数の引数を渡せるよう可変にしたい場合があります。ワークシートの関数では、引数の個数が不定の関数が多数あります。=SUM(数値1,数値2,...) このように、最後が「,...」となっていて、いくつでも(限度はありますが)指定できる関数です。

Left関数 , LeftB関数
Left関数は、文字列の左端から指定した文字数分の文字列を返します、バリアント型(内部処理形式StringのVariant)の値を返します。Left関数 Left(string,length) string 必ず指定します。この文字列式の左端から文字列が取り出されます。
Right関数 , RightB関数
Right関数は、文字列の右端から指定した文字数分の文字列を返します、バリアント型(内部処理形式StringのVariant)の値を返します。Right関数 Left(string,length) string 必ず指定します。この文字列式の右端から文字列が取り出されます。
IsNumeric関数|VBA関数
IsNumeric関数は、式が数値として評価できるかどうかを調べ、結果をブール型(True,False)で返します。IsNumeric関数 IsNumeric(expression) expression 必ず指定します。引数expressionには、数式または文字列式を含むバリアント型(Variant)の式を指定します。
IIf関数|VBA関数
IIf関数は、式の評価結果によって、2つの引数のうち1つを返します。IIf関数 IIf(expr,truepart,falsepart) expr 必ず指定します。評価対象の式を指定します。truepart 必ず指定します。



同じテーマ「マクロVBA技術解説」の記事

VBAでWEBカメラ操作する
VBAで電光掲示板を作成
ユーザーに絶対に停止させたくない場合のVBA設定
列幅・行高をDPI取得しピクセルで指定する
VBAでWMIの使い方について
アクティブシート以外のWindowを設定できるWorksheetView
LSetとユーザー定義型のコピー(100桁の足し算)
省略可能なVariant引数の参照不可をラップ関数で利用
ブックのいろいろな開き方(GetObject,参照設定,アドイン)
入力規則への貼り付けを禁止する
「Excel 4.0 マクロ」の使い方


新着記事NEW ・・・新着記事一覧を見る

VBA100本ノック 18本目:名前定義の削除|VBA練習問題100(11月6日)
VBA100本ノック 17本目:重複削除(ユニーク化)|VBA練習問題100(11月6日)
VBA100本ノック 16本目:無駄な改行を削除|VBA練習問題100(11月5日)
VBA100本ノック 15本目:シートの並べ替え|VBA練習問題100(11月4日)
VBA100本ノック 14本目:社外秘シート削除|VBA練習問題100(11月3日)
VBA100本ノック 13本目:文字列の部分フォント|VBA練習問題100(11月1日)
VBA100本ノック 12本目:セル結合を解除|VBA練習問題100(10月31日)
VBA100本ノック 11本目:セル結合の警告|VBA練習問題100(10月30日)
VBA100本ノック 10本目:行の削除|VBA練習問題100(10月29日)
VBA100本ノック 9本目:フィルターコピー|VBA練習問題100(10月28日)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
5.マクロって何?VBAって何?|VBA入門
6.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
7.繰り返し処理(For Next)|VBA入門
8.セルに文字を入れるとは(Range,Value)|VBA入門
9.とにかく書いてみよう(Sub,End Sub)|VBA入門
10.マクロはどこに書くの(VBEの起動)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。



このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ