• ベストアンサー

エクセル・解がある数字になるように足し算する数字を選ぶ方法

いくつかの数字が並んでいて、その中から選んで足し算をします。 その足し算の答えがある範囲内に当てはまるような組み合わせを全部求めたいと思います。 分かりにくいので具体例を書きます。 0.5 1.1 1.8 2.3 3.8 4.2 上記の6個の数字からいくつか選んで足した結果が4.9~5.9になる組み合わせをすべて求めたいです。 この場合、 0.5+1.1+1.8+2.3=5.7 1.1+1.8+2.3=5.2 4.2+0.5=4.7 4.2+1.1=5.3 4.2+1.1+0.5=5.8 3.8+1.8=5.6 3.8+1.1=4.9 3.8+1.1+0.5=5.4 の8種類(もっとあったらごめんなさい)になると思います。 この8種類を書き出したいのですが、うまい方法が思い浮かびません。 ソルバーとかなのかと思って調べてみたのですが、計算式が確定していない場合は使えないみたいです。 やっぱりVBAを使わないと難しいでしょうか? なんとか簡単にできる方法があれば、アドバイス下さい。 よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • lark_0925
  • ベストアンサー率63% (37/58)
回答No.2

>上記の6個の数字からいくつか選んで足した結果が4.9~5.9になる組み合わせをすべて求めたいです。 なら、 4.2+0.5=4.7 これは、範囲外だよね!! 組合せの最適化をすれば、もっと速いコードもありそうですが・・・。 新規ブックの標準モジュール(Module1)に '======================================================== Sub main()  Dim 組合せセル範囲 As Range  Dim 抜き取り数 As Long  Dim asum As Double  Dim 合計1 As Double  Dim 合計2 As Double  Dim d_rw As Long  Range("a1:a6").Value = [{0.5;1.1;1.8;2.3;3.8;4.2}]  MsgBox "サンプルデータをA列に設定"  合計1 = 4.9  合計2 = 5.9    d_rw = 1  Set 組合せセル範囲 = Range("a1", Cells(Rows.Count, "a").End(xlUp))  組合せセル範囲.Sort Key1:=Range("A1"), Order1:=xlAscending, Header:=xlNo  For 抜き取り数 = 1 To 組合せセル範囲.Count    Call init_comb(組合せセル範囲, 抜き取り数)    ReDim ans(1 To 抜き取り数)    Do While get_comb(ans()) = 0     asum = Application.Sum(ans())     If asum >= 合計1 And asum <= 合計2 Then       Range(Cells(d_rw, 3), Cells(d_rw, 抜き取り数 + 2)).Value = ans()       d_rw = d_rw + 1     ElseIf asum > 合計2 Then       skip_comb       End If     Loop    Next  MsgBox "以上、" & d_rw - 1 & " 通り検出しました" End Sub 別の標準モジュールに(Module2)に 組合せリスト作成ルーチン '=========================================================== Option Explicit   Private c_svn As Long '抜き取り数保存   Private c_myarray() '組合せ対象値の配列   Private c_idx() As Long '配列のカレントポインタ   Private cs_x() As Long '配列の基盤ポインタ '======================================= Function init_comb(rng As Range, seln As Long) As Double   Dim i As Long   Dim crng As Range   c_svn = seln   Erase c_myarray()   Erase c_idx()   Erase cs_x()   i = 1   ReDim Preserve c_myarray(1 To rng.Count)   For Each crng In rng    c_myarray(i) = crng.Value    i = i + 1    Next   ReDim cs_x(1 To seln)   ReDim c_idx(1 To seln)   For i = 1 To UBound(c_idx())    cs_x(i) = i    c_idx(i) = i    Next   c_idx(UBound(c_idx())) = c_idx(UBound(c_idx())) - 1   init_comb = WorksheetFunction.Combin(rng.Count, seln) End Function '======================================= Function get_comb(ans()) As Long   Dim i As Long   Dim j As Long   get_comb = 1   For i = UBound(c_idx()) To LBound(c_idx()) Step -1    If c_idx(i) + 1 <= UBound(c_myarray()) - c_svn + i Then      c_idx(i) = c_idx(i) + 1      get_comb = 0      Exit For    Else      c_idx(i) = cs_x(i) + 1      cs_x(i) = cs_x(i) + 1      For j = i + 1 To UBound(cs_x())       cs_x(j) = cs_x(j - 1) + 1       c_idx(j) = cs_x(j)       Next j      End If    Next   If get_comb = 0 Then    For i = LBound(c_idx()) To UBound(c_idx())      ans(i) = c_myarray(c_idx(i))      Next    End If End Function '======================================= Function skip_comb()   Dim i As Long   For i = UBound(c_idx()) To LBound(c_idx()) + 1 Step -1    If c_idx(i) <> c_idx(i - 1) + 1 Then      c_idx(i) = UBound(c_myarray()) - c_svn + i      Exit For      End If    c_idx(i) = UBound(c_myarray()) - c_svn + i    Next End Function '======================================= Sub close_comb()   Erase c_myarray()   Erase c_idx()   Erase cs_x() End Sub として、適当なシート(何も入力されていない)でmainを 実行してみてください。セルC1から条件にあった組合せを 表示します。

-yellowtail-
質問者

お礼

ありがとうございますー(T-T) おっしゃるとおり、4.7は範囲外でした(^-^; lark_0925様にいただいたコードを使ってみたら、理想通りの結果を得ることができました! 総当たりで足し算をしたとしても、その足している数字が何なのかを全部書き出すにはどうすれば…と思っていましたが、配列を利用すれば良かったのですね! 配列はなかなか難しくて、自分では使いこなせないのですが、lark_0925様のコードを見てなんとか理解しようと思います。 個人的には「Application.Sum(ans())」で合計を取れるということに感動しました! それにしてもすごいですね!!! こんなすぐにコードをかけてしまうなんて、尊敬です。 本当にとてもとても助かりました。 涙が出るほど嬉しいです。本当にありがとうございました。

その他の回答 (3)

  • NNAQ
  • ベストアンサー率56% (104/184)
回答No.4

数個なら。。。 A列にデータがあって、作業列が X~Z列だとして、    X   Y   Z 1          001010 2 000001  4.2  010001 3 000010  3.8  010010 4 000011  8   011100 5 000100  2.3  110001 6 000101  6.5  110010 7 000110  6.1  111100 : X2=TEXT(DEC2BIN(ROW(A1)),REPT("0",6)) X64までコピー(64=2^6)。 Y2=SUMPRODUCT($A$1:$A$6,MID(X2,ROW($A$1:$A$6),1)*1) Y64までコピー。 Y列にオートフィルターで [4.9以上]AND[5.9以下] の条件で抽出。 抽出されたX列のデータをコピー、Z1に[形式を選択して貼り付け]-[値]。   A   B  C  ・・・ 1 0.5  0  0 2 1.1  0  1 3 1.8  1  0 4 2.3  0  0 5 3.8  1  0 6 4.2  0  1 7    5.6  5.3 B1=MID(INDEX($Z:$Z,COLUMN(A1)),ROW(A1),1)*1 B6までと、右へコピー。 B7=SUMPRODUCT($A1:$A6,B1:B6) 右へコピー。 1と0 で、その数字を使う使わない の判定にします。7行目は確認用。 B列は 1.8 + 3.8 = 5.6 C列は 1.1 + 4.2 = 5.3 という意味です。 VBA でやるなら、2つ足す場合、3つ足す場合、4つ足す場合・・・ と、やると、遅くなると思います。 総当りはどんな方法でも限界があるでしょうけど。 'データは、A1セルから空白無く、複数あるとする Sub SoAtari()  '目標値  Const a As Currency = 4.9 '以上  Const z As Currency = 5.9 '以下  Dim n As Integer 'データ数  Dim arr0, arr1() As Currency  Dim b As Long  Dim i As Long, j As Long 'ループ用、使い回し  Dim col As Integer '列番号  With Range("a1")   n = .End(xlDown).Row   arr0 = .Resize(n).Value   .CurrentRegion.Offset(, 1).ClearContents  End With  '全ての組み合わせの和を配列arr1にセット  '全て計算する必要は無いので、改善の余地あり  ReDim arr1(1 To 2 ^ n - 1)  For i = 0 To n - 1   b = 2 ^ i   arr1(b) = CCur(arr0(i + 1, 1))   For j = 1 To b - 1    arr1(b + j) = arr1(b) + arr1(j)   Next j  Next i  col = 2  For i = 1 To 2 ^ n - 1   '目標値の範囲ならシートへ書き込む   If arr1(i) >= a And arr1(i) <= z Then    For j = 0 To n - 1     If i And 2 ^ j Then Cells(j + 1, col).Value = arr0(j + 1, 1)    Next j    Cells(n + 1, col).Value = CDbl(arr1(i))    col = col + 1   End If  Next i  Erase arr0, arr1 End Sub

-yellowtail-
質問者

お礼

ありがとうございます! すごい!!関数でもできるんですね。 0と1を使って使うかどうかの判定をしたり、それを組み合わせで全通り表示する方法など、たぶん一生考えても思いつけそうにありません。 感動しました(T-T) 9個まではちゃんとできました! 10個からは2進数が表示されないみたいでエラーになってしまいました。 VBAの改善とは、上限を超えた場合は計算をしなくても良いということですよね。 でも、試しに動かしてみたら速度に問題なく計算できました!! 結果が一覧になっていてとても見やすかったです。 とてもとても勉強になりました。 やはり配列はちゃんと勉強すればとても役立つのだと思いました。 ありがとうございました!!大感謝です。

  • lark_0925
  • ベストアンサー率63% (37/58)
回答No.3

追伸 A列のデータは、昇順に整列されているものとします。

-yellowtail-
質問者

お礼

了解しました。

  • n-jun
  • ベストアンサー率33% (959/2873)
回答No.1

類似していると言えば、 http://okwave.jp/qa257719.html でしょうか。 ただ固定された答えではなく範囲内に入る組み合わせとなると、 もっとやっかいになるように思います。 回答ではなく、すいません。

-yellowtail-
質問者

お礼

本当にやっかいで、私一人ではどうにも解けず、ここに相談してみました。 ご回答ありがとうございます(^-^)

関連するQ&A

  • エクセル「3つの数字の合計がある数字になる組み合わせ」を調べたい。

    こんにちは。 エクセルで、以下のような問題を解くことはできますでしょうか? 基本的な関数しかできず、自分で調べたところ。ソルバーやVBAを使えばできるのかもしれないとは思ったのですが、なかなか良い類似例を見つけられず、苦戦しています。 <問題> 「3」「5」「6」「8」…といったランダムな数字が合計になる3つの数字のすべての組み合わせを知りたいです。 たとえば、 「3」なら答えは「1+1+1」 「5」なら答えは「2+1+1」「1+2+1」「1+1+2」 「6」なら答え「4+1+1」「1+4+1」「1+1+4」「3+2+1」「2+3+1」「1+2+3」「3+2+1」…のような形です。 ※実は子どもの名付けで、画数の組み合わせを出そうと思っています。 わかりづらい点があるかとは存じますが、お力添え何卒よろしくお願い致します。

  • エクセルでの、たし算方法は?

    私は計算と言うと エクセル位しか知らないんですが 今迄、使った事が、ありません で、現在、平均点の計算を、してるんですが 今迄は、3ケタの数字をメモ帳に入力 それを数十個入れた後、全部を足して 平均点を出してました ちなみに入力方法は 「a652 597 b484 417 c589 688 d477…」 なんですが、数字の前に アルファベットを入力してのは 入力数を分かり易くする為で 例えば「j600」迄の入力で、平均点を出す場合 いちいち、全部の数字の数を数えなくても “j”はアルファベットの10個目ですから 10×2で、合計20個で割ってました しかし、足し算は計算機を使用してましたから 入力ミスを、する時や時間が掛かる為 これをエクセルで出来ないかと考えました ハッキリ言って、数字を入力する時に 一緒に計算機で、同時計算をすれば、一番早いんですが 入力するのに時間が短く 計算機で同時計算の余裕がありません ただ、自分でもエクセルの使用方法を検索等で調べたんですが 私が分かったのは 1セル(?)の中に全ての文字を “+”で入れて合計を出す方法と セルの中に、数字を入れて 後からセルと“+”で合計する方法です でも、全ての数字と“+”では 1セルの中が見え難くなりますし 入力後にセルと“+”では二度手間で しかも、クリックの押し間違いが出る時があります そこで聞きたいんですが セルの中に数字を入れながら、自動で計算出来る… 又は、平均点も簡単捜査で出来る方法を 御存じないでしょうか?

  • エクセルでたし算 いろんな方法があると思う・・・

    これまたくだらない質問です エクセルの計算です (以下イメージ) [一万円] * □ 、[五千円] * □ ~ 1円 * □ 全部の紙幣、貨幣のたし算です。 □の中には枚数を入力します これの合計(で任意のセルに金額が出ます)を出したいのです 他のセルに式 (=*10000)とかでも良いのですが もっと良い方法はないでしょうか(他のセルに飛ばさずに) VBAとかになるとお札アイコンとか作りたくなってしますのでそれ以外でお願いします (本当はお札 and 貨幣 アイコンをポチポチすると枚数が増える&合計金額が でるにしたいのですが今回はなしで) よろしくお願いします

  • エクセルで、1つのセルで上書き足し算できますか?

    こんばんは パソコン初心者です。お時間があったらお答えをおねがいします!たとえばエクセルで1つのセルに10と入力しておいて、そのあと5を足し算したいときに、 他のセルを使わないで、その10と入力してあるセルに、上書きのようなかたちで簡単に足し算できないでしょうか? (10、のあと5、エンター、で足し算完了のような。。。) 実際はもっと長い数字なのですが、いまは先に計算しておいて入力してます。。。簡単にできたらいいなぁと思っています。

  • 足し算の組み合わせ

    組み合わせの足し算について質問します。 1,2,3という数字があったとします。 たとえば、この1,2,3を2系列用意し、それぞれ足します。 考えやすくするため、2系列を次のようにあらわします。 A系列=1,2,3 B系列=1,2,3 また、A系列の1をA1、B系列の2をB2などのように表現します。 考えられる組み合わせの足し算は次のようになります。 A1+B1=2 A1+B2=3 A1+B3=4 A2+B1=3 A2+B2=4 A2+B3=5 A3+B1=4 A3+B2=5 A3+B3=6 そして、ここから重複を排除すると、残る足し算の結果は、 2,3,4,5,6となります。 これをVBAでプログラミングしたいのですが、どのように考えればよいでしょうか。 もちろん、実際は、1,2,3・・・xまで可変とし、系列数も可変とします。 ただし、すべての系列は同じです。 つまり、A系列=1,2,3、B系列=1,2,3,4ということはありません。 たとえば、A系列が1,2,3,4だったら、のこりの系列もすべて1,2,3,4です。

  • 足し算の計算速度

    こんにちは。 足し算の計算速度を測ってみました。 すると、全く同じ条件で、足す値だけ変えてみると 計算速度が変わりました。 具体的には、ガウス分布を単純に台形公式で積分したのですが、 積分範囲と平均値を固定して、分散を小さくすると 積分時間が異常に長くなりました。 小さい値(10e-200)とかの足し算は遅くなるのですか? また、理由もあれば教えていただけないでしょうか? 宜しくお願いします。

  • エクセルで計算した結果をメールで送る方法

    エクセルで計算した結果をメールで送りたいのですが、エクセルをそのまま添付するのではなく、エクセルで計算した結果を文章でメール送信したいのですが、方法はありますか?具体的には、エクセルで簡単な足し算を行った結果をメールで送信したいのです。昨日○件 今日○件 合計○件 VBAなどを使い、数字を入力し、ボタンを押すだけでアウトルック等で送信できるようにしたいのです。

  • エクセルで数字をドラックして計算の答えを出したい

    エクセルで複数の数字をドラックすると足し算の答えが 出せる機能があると思ったのですが、画面の右下辺りに答えが 出たような気がします。 忘れてしまったのでどなたか方法を教えてください。

  • 数字の組み合わせを教えて!

    7つの数字から4つの数字の組み合わせがいくつ出来ますか?(1,2,3,4)と(4,3,2,1)は使われている数字が同じなので1つと数えます。実際に書き出して、同じ組み合わせを探して消していくと凄い時間が掛かるので計算方法を知っている方教えて下さい! ◎7つの数字から4つの数字の組み合わせがいくつ出来ますか? ◎8つの数字から4つの数字の組み合わせがいくつ出来ますか? ◎9つの数字から4つの数字の組み合わせがいくつ出来ますか? ◎10この数字から4つの数字の組み合わせがいくつ出来ますか?

  • 数字の組み合わせ方法について教えてください

    趣味のロト6で候補の数字を選択したものを組み合わせるのに苦労しています。 そこで、12個の数字から6個の数字の組み合わせを早く作れる方法(計算式でも可)をアドバイスください。 お願いします。

専門家に質問してみよう