0.1~1.0未満の乱数を10000個生成しヒストグラムを作る問題が解けずに困っております。
- 評価
- クリップ 0
- VIEW 190
10000個生成した乱数を
1:0.0~0.2
2:0.2~0.4
3:0.4~0.6
4:0.6~0.8
5:0.8~1.0
のレベルに分類して、
縦軸を1000、2000,3000とし、
横軸を分類した1、2、3、4、5、としたヒストグラムを作成したいのですが
生成した乱数をグラフになかなかできません。
また、乱数の生成のさせ方は下のソースコードのような形でよろしいのでしょうか。
教えて欲しいです。
import java.util.Random;
public class S7015507_Kadai1_5{
//メインメソッド
public static void main (String[] args){
//Randomクラスのインスタンスを生成
Random rnd = new Random();
double dbl_data;
//カウンタを用意し、初期化
int [] count_dbl_data={0,0,0,0,0,0,0,0,0,0,};
//double型の乱数(0〜100未満)を10000個生成し、表示
System.out.println("double型の乱数を生成");
for (int i=0; i<10000; i++){
dbl_data =rnd.nextDouble();
//if文でカウンタに振り分け
if(dbl_data<0.1){
count_dbl_data[0]++;
}
else if(dbl_data<0.2){
count_dbl_data[1]++;
}
else if(dbl_data<0.3){
count_dbl_data[2]++;
}
else if(dbl_data<0.4){
count_dbl_data[3]++;
}
else if(dbl_data<0.5){
count_dbl_data[4]++;
}
else if(dbl_data<0.6){
count_dbl_data[5]++;
}
else if(dbl_data<0.7){
count_dbl_data[6]++;
}
else if(dbl_data<0.8){
count_dbl_data[7]++;
}
else if(dbl_data<0.9){
count_dbl_data[8]++;
}
else{
count_dbl_data[9]++;
}
}
//各レベルの表示
for(double i=0; i<10; i++){
System.out.println("0.0~0.1未満"+count_dbl_data[0]);
System.out.println("0.1~0.2未満"+count_dbl_data[1]);
System.out.println("0.2~0.3未満"+count_dbl_data[2]);
System.out.println("0.3~0.4未満"+count_dbl_data[3]);
System.out.println("0.4~0.5未満"+count_dbl_data[4]);
System.out.println("0.5~0.6未満"+count_dbl_data[5]);
System.out.println("0.6~0.7未満"+count_dbl_data[6]);
System.out.println("0.7~0.8未満"+count_dbl_data[7]);
System.out.println("0.8~0.9未満"+count_dbl_data[8]);
System.out.println("0.9~1.0未満"+count_dbl_data[9]);
}
}
}
-
気になる質問をクリップする
クリップした質問に回答があった場合に通知・メールを受け取ることができます。
クリップした質問はマイページの「クリップ」タブからいつでも見ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+5
乱数の生成のさせ方は下のソースコードのような形でよろしいのでしょうか。
致命的な間違いはないと思いますが、「あまりよくない」と思えることがあるのでコメントしてみます。
dbl_data
宣言をfor文の外側で行っています。しかしこの変数にアクセスしているのはfor文の内側のブロックの中だけです。こんなときはfor文の内側で宣言した方がよいと思います。「変数を宣言するとその度に何かの処理が動いて遅くなるような気がする」ことがあるかも知れませんが、Javaであればそういうことを気にする必要はありません。(大抵のコンパイラー言語でも同様だと思います)count_dbl_data
初期値として{ 0, 0, ... }
のような構文を使っていますね。要素数を注意深く数えると必要な要素分だけ定義できているかどうか確認はできますが、しかし値が全て0なので、こう書くよりは必要な要素数を用いてnew int[5]
と書いた方が明快です。if文の羅列
こういう「同じような処理を並べる」のは「書くときに間違い易く、また間違いがないかを確認するときにめんどくさい」ため多くのプログラマーはいやがると思います。プログラミングに慣れてくると「いかに単純にかけるか」をだんだんとうまく書けるようになってきます。ここでやりたいことは「ある値が等間隔で区切られた区間のどこに属するか」なのですが、次のような工夫ができます。つまり30行程度のif文の羅列が2行で済むことに・・・
int index = (int)(dbl_data * 5);
count_dbl_data[index]++;
このようなコードを間違いなく書くにはある程度の知識も併せて必要です。乱数は絶対に1未満の値でありそれを5倍して整数化しても「決して5以上の値にはならない」ことが確信をもってわかっていなければなりません。
- count_dbl_data再び
上の指摘でnew int[5]
の方がよいと書きました。しかし5はmagic numberと呼ばれる「プログラムに出現する意味がよくわからない定数」として嫌われることがあります。プログラムの論理は任意の数を5個の区分に分類して集計するので5に名前をつけたほうがより明快になります。
static final int NUM_OF_CLASSIFICATIONS = 5;
...
int[] count_dbl_data = new[NUM_OF_CLASSIFICATIONS];
for (...省略...) {
...省略...
int index = (int)(dbl_data * NUM_OF_CLASSIFICATIONS);
count_dbl_data[index]++;
}
- 変数名
自分も人のことを言えるほどはうまくできないのですが・・・昔ある人に「変数やクラスの名前の最後にdataとかinformation」と付けるのはナンセンスと言われたことがあります。「プログラムで扱うのはなんでもそうだけど、何かのデータや情報なんだからdata, informationとわざわざ付けるのは筋がわるい」というのがその人の主張でした。自分はその主張をもっともに感じたのでdataなどの単語が使いたくなった時に「ちょっと待て!」と考えるようになりました。
本プログラムの例でいえばdbl_dataでなくて単にvalueでよいし、count_dbl_dataは単にcountersでよいかも知れません。(英語センスがない自分はこうした名前を考えるとき結構まよったりします。が、ちょっと考えてよりましな名前を付けられるならそれは無駄ではないと思っています)
縦軸を1000、2000,3000とし、
横軸を分類した1、2、3、4、5、としたヒストグラムを作成したいのですが
生成した乱数をグラフになかなかできません。
本当の質問意図はこちらの方だと思いますが、上のコメントのうち「if文を減らすためにある値を別の値へ変換する」ことや「繰り返し文の中でどのように共通の書き方をするか」が考えらるようになってくるとヒストグラムを作るという論理が考えられると思います。
1000, 2000, 3000に到達しているかどうかを以下のようなループでしか書けないとしたらプログラムを書くのは大変苦痛になることでしょう。
for (int i = 0; i < count_dbl_data.length; i++) {
if (count[i] > 3000) {
System.out.print(" * ");
} else {
System.out.print(" ");
}
}
System.out.println();
for (int i = 0; i < count_dbl_data.length; i++) {
if (count[i] > 2000) {
System.out.print(" * ");
} else {
System.out.print(" ");
}
}
System.out.println();
...
具体的なヒントでなくてゴメンナサイ。
投稿 2017/06/20 16:59
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
以下のような回答は評価を下げられます
- 間違っている回答
- 質問の回答になっていない投稿
- 不快な投稿
評価を下げる際はその理由をコメントに書き込んでください。
0
JavaのRandom::nextDouble()は0.1~1.0の範囲の乱数になりますが、小数第1位の以下の値も入ってきます。(例えば0.2345・・・もあるということ)
なので、整数で0~9までの乱数を取得して+1した上で10で割って0.1~1.0の乱数を作ればいいと思います。
bl_data = (double)(rnd.nextInt(10) + 1) / 10.0;
投稿 2017/06/20 17:35
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
以下のような回答は評価を下げられます
- 間違っている回答
- 質問の回答になっていない投稿
- 不快な投稿
評価を下げる際はその理由をコメントに書き込んでください。
0
他の方がソースについてはいろいろ詳しくかかれているので。
「乱数の生成のさせ方は下のソースコードのような形でよろしいのでしょうか。」
というところだけ補足。
Javaの乱数生成はどのパッケージの"Random"を選ぶかが実は重要。
java.util.Randomはぶっちゃけ偏ります("Java 乱数 偏り"で検索検索)。
他の選択肢としては
1.java.security.SecureRandom
2.java.lang.Math#random()
3.メルセンヌツイスタ使う
セキュリティなら1必須、製品に使うなら3、とりあえず生のjava.util.Randomより品質を求めるなら2とか(あと並行処理で性能でるやつとかあるそうですが、使ったことは無い)。
投稿 2017/06/22 14:40
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
以下のような回答は評価を下げられます
- 間違っている回答
- 質問の回答になっていない投稿
- 不快な投稿
評価を下げる際はその理由をコメントに書き込んでください。
15分調べてもわからないことは、teratailで質問しよう!
91.87%
質問への追記・修正、ベストアンサー選択の依頼
fuzzball
2017/06/20 16:02
コードは ``` で囲って下さい。あと、タイトル間違ってます。
LgjtY1j6PUkCqKA
2017/06/20 16:07
初めての投稿でよくわからなくて、申し訳ございません。タイトルはどのようになおせばよろしいのでしょうか?
LgjtY1j6PUkCqKA
2017/06/20 16:24
やっとわかりました。嫌な思いさせてしまい、申し訳ございませんでした。