プロが教える店舗&オフィスのセキュリティ対策術

説明が下手ですみませんが、よろしければお教えください

複数の数の和が目的の値にもっとも近くなる計算をしたいと思ってます
複数の数それぞれも、目的の値も、その都度ことなります
目的の値を越えてはいけません

たとえば…
目的が100に近付けることで
数の候補は、28,30,45,65である場合は
30+65=95で100にもっとも近くなります、という解答をしてくれるソフトです
ただし28+30+45=103と、100との差が3なのでより近いと言えますが、目的の値を越えてはいけないので、こういう解答をキャンセルしてくれる必要があります

こういった計算ができるソフトがありましたら、よろしくご紹介お願いいたします

A 回答 (4件)

Excel が使えるなら、ソルバー機能を使ってはいかがでしょうか。


https://www.google.co.jp/search?q=solver+excel

● 前提
1行目に、数の候補を記載 (例) 28, 30, 45 , 65
2行目に、個数の初期値 0 を記載
3行目に、"= 1行目のセル * 2行目のセル" の計算式を記載
4行目に、3行目の総和を求める計算式を記載

● ソルバーのパラメーター
目的セル: 4行目の計算式のあるセル
目標値: 最大値
変数セル: 2行目の各セル
制約条件:
* 2行目の各セル <= 1
* 2行目の各セル = 整数
* 4行目の計算式のあるセル <= 100
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます
リンク先のリンク先を見てみました
ちょっと難しい気はしましたが希望している計算を実現してるようには感じました
これはまず読んで理解するのに時間がかかりそうですねw

お礼日時:2017/05/24 12:44

Excelでこのように表(添付画像)を作ってみるのはどうですか?


If関数と、足し算、引き算だけ使えれば、できます。
全てのパターンを入力するのも手間ですが、
数の候補が3つの場合、4つの場合、5つの場合と、使いまわせる書式を作ってしまえばいいと思います。

目視で回答を探しても良いし、Abs関数、Min関数など使えば、回答を出すこともできます。
「複数の数から、目的に近い値になるよう選択」の回答画像3
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます
なるほど、これだと手が届くかも、と感じます
ただ扱う数が、例では少なめにしてましたが実際はもっと多いので
そこを簡単に数値を入力しさえすれば解答がポンと出る計算ソフトを希望してました
時間を見つけて試してみたいと思います

お礼日時:2017/05/24 12:39

このような問題は、組合せ最適化問題というクラスになります。


質問の問題だとナップサック問題になるかと思いますが、対象の数が少ないうちは総当たりでも解けるのですが、ちょっと大きくなると指数的に難しくなる問題です。

この手の最適化問題を解くツールは、あるにはありますが、売り物が多いですね。フリーだとGLPKくらいでしょうか。
また問題の正確な記述が必要なので、ツール独自の問題記述言語があったりします。

最適化問題ソルバーのGLPKを使ってみた
http://qiita.com/anqooqie/items/dc6498909efd7b2d …

あとはプログラミング言語のライブラリとして提供されているものもあったりしますね。
下記URLではPythonライブラリを使った例が出ています。

組合せ最適化を使おう
http://qiita.com/SaitoTsutomu/items/bfbf4c185ed7 …
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます
ご紹介いただいた2件を拝見しましたがチンプンカンプンでしたw
どうも思ってたより難しいQだったみたいですね
丁寧に教えていただけて嬉しく思います

お礼日時:2017/05/22 15:32

そのようなピンポイントの計算をさせるなら、自分でプログラムを組みましょう


以下のように総当たりで簡単に求まります。

#include <stdio.h>
int main(int argc, char **argv) {
if (argc < 3) {
printf("usage: %s target numbers...\n", argv[0]);
return 1;
}
int i;
int target = atoi(argv[1]);
int ns = argc - 2;
if (ns > 64) return 1;
int n[64];
unsigned long long int limit = 1;
for (i=0; i<ns; i++) {
n[i] = atoi(argv[2+i]);
limit <<= 1;
}
unsigned long long int mask, rmask = 0;
int rmax = 0;
for (mask = 1; mask < limit; mask++) {
int s = 0;
for (i=0; i<ns; i++) if ((mask>>i) & 1) s += n[i];
if (rmax < s && s <= target) rmax = s, rmask = mask;
}
for (i=0; i<ns; i++) if ((rmask>>i) & 1) printf("%d ", n[i]);
printf(": %d\n", rmax);
return 0;
}
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます
こ、これは…うーんw
恐縮ですが、これをどうして良いかすら判らず、とても自分の手には負えません

お礼日時:2017/05/22 15:36

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!