はじめて投稿します。C言語について完全に初心者なのでよろしくお願いします。
説明が下手で伝わりにくかったらすみません。
ひとつの値Xを5つに分類しようとしています。
5つをa,b,c,d,eとすると、それぞれの割合を0.3,0.4,0,1,0.1,0.1とします。(合計が1)
X=6とすると、それらをかけてa=1.8,b=2.4,c=0.6,d=0.6,e=0.6となります。
しかし、a,b,c,d,eは整数なので、まず1の位だけを見て、すべてを合計するとa=1,b=2,c,d,e=0となります。
これでは、a~eの合計が3なので、これを6にするにはあと3必要です。
そのため,小数第一位だけをみて大きい順に1プラスしていきます。
まず、aを1プラスします。残りが2つでa~eをみるとc,d,eが同じ値なのでこの中から2つを
1プラスします。この選び方はランダムとします。今回はdとeをプラスすることにします。
結果としてふりわけられた値は
a=2,b=2,c=0,d=1,e=1 となります。
Xの値はtextBoxで入力し、割合は決まっているものとし、
振り分け結果が出力されるようなプログラムがつくりたいです。
C++を使っています。どのようなプラグラムを作ればこのようなことができるのか教えてほしいです。
よろしくお願いします。
ふりわけプログラム
Re: ふりわけプログラム
割合が、小数点以下1桁だと限定すれば、
3:4:1:1:1と考えることができます。Xが整数なら、(たとえば6なら)
18:24:6:6:6ですね。したがって10で割った商は
1:2:0:0:0となり、10で割った時の余りは
8:4:6:6:6です。この余りが大きいほうから割り振ればいいと思います。
小数点以下1桁だと限定できないなら、浮動小数点で考慮しなくてはいけないので、
小数点以下だけを取り出し、ソートする方法があります。
3:4:1:1:1と考えることができます。Xが整数なら、(たとえば6なら)
18:24:6:6:6ですね。したがって10で割った商は
1:2:0:0:0となり、10で割った時の余りは
8:4:6:6:6です。この余りが大きいほうから割り振ればいいと思います。
小数点以下1桁だと限定できないなら、浮動小数点で考慮しなくてはいけないので、
小数点以下だけを取り出し、ソートする方法があります。
non
Re: ふりわけプログラム
返信ありがとうございます。
頭では理解できるんですけど、いざプログラムにしようとすると難しいです。
できればサンプルでも良いのでプログラムを教えて頂けないでしょうか。
頭では理解できるんですけど、いざプログラムにしようとすると難しいです。
できればサンプルでも良いのでプログラムを教えて頂けないでしょうか。
Re: ふりわけプログラム
プログラムにするのが難しいとのことですが
今の時点ではどれが書けますか?
1.xの値を代入させる
2.xに割合をかけた値a,b,c,d,eを求める
3.a,b,c,d,eの整数部分を出し、余りを求める
4.a,b,c,d,eの小数点以下を出す
5.a,b,c,d,eの小数点以下のうち最大のものはどれかを求め、
その整数部分に1をたす。
6. 余りがなくなるまで5をループさせる
7.結果表示
今の時点ではどれが書けますか?
1.xの値を代入させる
2.xに割合をかけた値a,b,c,d,eを求める
3.a,b,c,d,eの整数部分を出し、余りを求める
4.a,b,c,d,eの小数点以下を出す
5.a,b,c,d,eの小数点以下のうち最大のものはどれかを求め、
その整数部分に1をたす。
6. 余りがなくなるまで5をループさせる
7.結果表示
- bitter_fox
- 記事: 607
- 登録日時: 13年前
- 住所: 大阪府
Re: ふりわけプログラム
横からで申し訳ないですが、以下nonさんが提示したアルゴリズムのサンプルプログラムです。
あくまでサンプルです。それぞれサンプルをコピペでつなげるだけでは、本来の動作をしません。(というより、もしかしたらこっちから答えを見つけるほうが難しいかも??)
あと「この選び方はランダムとします」ということなので、そのことも考慮しました。
[hr]
修正(algolism ==> algorism)
//3:4:1:1:1と考えることができます。Xが整数なら、(たとえば6なら)
//18:24:6:6:6ですね。 (Mr.non's algorism)
void test() // programmed by bitter_fox
{
int counter;
int raito[5] = {3, 4, 1, 1, 1};
int X = 6;
for (counter = 0; counter < 5; counter++)
{
raito[counter] *= X;
}
}
//18:24:6:6:6ですね。
//したがって10で割った商は1:2:0:0:0となり (Mr.non's algorism)
void test() // programmed by bitter_fox
{
int counter;
int raito[5] = {18/10, 24/10, 6/10, 6/10, 6/10};
int now = 0;
for (counter = 0; counter < 5; counter++)
{
now += raito[counter];
}
}
//10で割った時の余りは8:4:6:6:6です。
//この余りが大きいほうから割り振ればいいと思います。 (Mr.non's algorism)
void test() // programmed by bitter_fox
{
int counter, counterY;
int raito[5] = {18%10, 24%10, 6%10, 6%10, 6%10};
int buf_raito[5] = {18%10, 24%10, 6%10, 6%10, 6%10};
int random[5] = {3, 4, 0, 2, 1}; // この値を添え字に使うことでランダム性を作る。当然実際の値は、実行時にランダムに作る
int X = 6;
int now = 3;
int temp;
for (counter = 0; counter < 5; counter++)
{
for (counterY = 5-1; counterY > counter; counterY--)
{
if (buf_raito[counter] < buf_raito[counterY])
{
temp = buf_raito[counter];
buf_raito[counter] = buf_raito[counterY];
buf_raito[counterY] = temp;
}
}
}
for (counter = 0; counter < X - now; counter++)
{
buf_raito[counter%5] += 10;
}
for (counter = 0; counter < 5; counter++)
{
for (counterY = 0; counterY < 5; counterY++)
{
if (raito[random[counter]] == buf_raito[counterY]%10) // 同じ余りのものがあったら
{
raito[random[counter]] += (buf_raito[counterY]/10)*10;
buf_raito[counterY] = 0; // リストからはじく。
break; // 見つかったので、後ろの検索をせずに飛び降りる
}
}
}
}
あと「この選び方はランダムとします」ということなので、そのことも考慮しました。
[hr]
修正(algolism ==> algorism)
Re: ふりわけプログラム
C言語について完全に初心者と書いていたので
配列を使わないものを考えていたのですが、
余りをランダムに振り分ける場合があることを考えると
配列を使った方がよいですね。
bitter_foxさんのサンプルのうち
3つめで得られるraitoはprintfなどで表示させるようにすればわかりますが
答えそのものではありません。
3.について
もし、小数をそのまま扱いたい場合は
y=(int)x;
とすることで小数xの整数部分をyに代入できます。
配列を使わないものを考えていたのですが、
余りをランダムに振り分ける場合があることを考えると
配列を使った方がよいですね。
bitter_foxさんのサンプルのうち
3つめで得られるraitoはprintfなどで表示させるようにすればわかりますが
答えそのものではありません。
3.について
もし、小数をそのまま扱いたい場合は
y=(int)x;
とすることで小数xの整数部分をyに代入できます。
Re: ふりわけプログラム
みなさん返信ありがとうございます。丁寧に教えていただいて本当にうれしいです。
まだまだ勉強不足だと思いました。 いろいろ勉強して、教えてもらったことを参考に頑張りたいと思います。
まだまだ勉強不足だと思いました。 いろいろ勉強して、教えてもらったことを参考に頑張りたいと思います。
- bitter_fox
- 記事: 607
- 登録日時: 13年前
- 住所: 大阪府
Re: ふりわけプログラム
ですね。Tatu さんが書きました: bitter_foxさんのサンプルのうち
3つめで得られるraitoはprintfなどで表示させるようにすればわかりますが
答えそのものではありません。
raito[5]の宣言時に、%10している所為ですね。
本当は、raito[5]には{18, 24, 6, 6, 6}が入っているのでその状態が維持されているようにサンプルを作るべきでしたね。。
修正版です。以下では、適切な答えが出るはずです。
///////////////////////////////////////////////////////////////////////////
// 修正版
///////////////////////////////////////////////////////////////////////////
//10で割った時の余りは8:4:6:6:6です。
//この余りが大きいほうから割り振ればいいと思います。 (Mr.non's algorism)
void test() // programmed by bitter_fox
{
int counter, counterY;
int raito[5] = {18, 24, 6, 6, 6}; // 修正点(この時点では、この状態が維持されていなければならない)
int buf_raito[5] = {18%10, 24%10, 6%10, 6%10, 6%10};
int random[5] = {3, 4, 0, 2, 1}; // この値を添え字に使うことでランダム性を作る。当然実際の値は、実行時にランダムに作る
int X = 6;
int now = 3;
int temp;
// ソートする(バブルソート)(降順)
for (counter = 0; counter < 5; counter++)
{
for (counterY = 5-1; counterY > counter; counterY--)
{
if (buf_raito[counter] < buf_raito[counterY]) // より大きいのが見つかったら
{
temp = buf_raito[counter]; // 入れ替える
buf_raito[counter] = buf_raito[counterY];
buf_raito[counterY] = temp;
}
}
}
// 足りない分だけ1(ここではすべての値を10倍しているので10)足していく
for (counter = 0; counter < X - now; counter++)
{
buf_raito[counter%5] += 10; // もしカウンターが5以上になると配列の外を参照するので %5 で巡回
}
for (counter = 0; counter < 5; counter++)
{
for (counterY = 0; counterY < 5; counterY++)
{
// 修正点(raito[random[counter]]のほうも10の剰余を求めるようにする)
if (raito[random[counter]]%10 == buf_raito[counterY]%10) // 同じ余りのものがあったら
{
raito[random[counter]] += (buf_raito[counterY]/10)*10;
buf_raito[counterY] = 0; // リストからはじく。
break; // 見つかったので、後ろの検索をせずに飛び降りる
}
}
}
// 以下追記(出力できるように)
for (counter = 0; counter < 5; counter++)
{
printf("%d, ", raito[counter]/10);
}
printf("\b\b \n"); // 最後の余分なコンマを削除
}
[hr]
追記:ソース内のコメントを増やしました。
Re: ふりわけプログラム
質問の条件をそのままコードにしました。
いちいち最大値を探すので効率は悪いですが、
それほど問題にならないと思います。
いちいち最大値を探すので効率は悪いですが、
それほど問題にならないと思います。
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
void func(int a[], int n, double d[])
{
double tmp_d[5], tmp_i;
int i, sum = 0;
for(i = 0; i < 5; ++ i){
tmp_d[i] = modf(n * d[i], &tmp_i);
a[i] = (int)tmp_i;
sum += a[i];
}
srand((unsigned)time(NULL));
while(sum < n){
int max = 0;
for(i = 1; i < 5; ++ i){
if(tmp_d[i] > tmp_d[max] || (tmp_d[i] == tmp_d[max] && rand() % 2)){
max = i;
}
}
++ a[max];
++ sum;
tmp_d[max] = -1;
}
}
int main(void)
{
int a[5], n = 6, i;
double d[5] = {0.3, 0.4, 0.1, 0.1, 0.1};
func(a, n, d);
for(i = 0; i < 5; ++ i) printf("%d ", a[i]); putchar('\n');
return 0;
}