ようこそ ゲスト さん、新規登録(無料)して気になる疑問を解決しませんか?

質問

質問者:adomi double配列を戻り値としたメソッド
困り度:
  • すぐに回答を!
最近Javaを始めたのですが、あまり知識がなく勘で書いているため今回配列の戻り値でつまずいてしまいました。
プログラムは一応VB,C#,Cをそこそこ書けるだろうといったレベルだと思っています。

問題はタイトル通りなのですが、Tryの中にdouble[] doubFuv = Hunx((int)intpara);
として、Hunx(同じクラスにstaticで宣言)は単純に配列を引数分作ってrundi[i] = Math.random();とし、最後にそのままreturn rundiしています。
ここでHunx内でprintlnして実行を確認すると正常に配列に値がはいているのですが、戻り値を受け取った側のdoubFuvには配列の中の幾つかが欠落(本来は0~1までの乱数のはずが、全体の3割に0.0が混入)してしまうといった今まで出会ったことのない状態になっています。
おそらくスレッドで何かぶつかっているのだと思いロックしてみようかと思いましたが、その方法もわからず途方に暮れています。

解決のヒントでもいいので、よろしくお願いいたします。
質問投稿日時:09/10/18 11:25
質問番号:5376208
この質問に対する回答は締め切られました。
最新から表示回答順に表示良回答のみ表示

回答

良回答10pt

回答者:pribaoutki なるべく文章化せずにソースコードそのまま提示するようにしてください。極端に長いコードでない限り。
No.1で示したコードで合っていたようですが、まだ「printlnして実行を確認」したあたりのコードが分かりません。

No.1のコードに加えて、メソッドからreturnする直前と、メソッドから戻り値を受け取った直後にそれぞれ、
 for (int i = 0; i < intpara; i++) {
   System.out.println(i+" "+rundi[i]);
 }
を挿入してあるだけなら、絶対に(と敢えて断言しますが)数値が化けることはありません。
(乱数にバグがあったとしても欠落とは関係ありません)
欠落の原因となっているプラスアルファのコードがあるはずです。

決して根の深い問題ではないという予感がします。ベテランプログラマも逃れられない不治の病「ポカミス」かと。
ローカル変数ではない変数(メンバー変数)があって、他のスレッドからいじられているとか。
あるいは、意図したメソッドとは違うメソッドを呼んでしまっているとか。
メソッドがオーバーライド(継承したクラスによるメソッド置き換え)またはオーバーロード(引数パターンの違う同名メソッド)されていると、メソッド名が同じために取り違えのミスが起こりやすいです。
種類:アドバイス
どんな人:専門家
自信:参考意見
回答日時:09/10/20 01:35
回答番号:No.5
この回答への補足返信が遅れてしまい申し訳ありませんでしたm(><)m
いろいろ本などを漁って見たところ、JavaはCなどのように配列を引数として渡すとアドレス参照となり、
C#でいうref修飾子が適応されたみたいな状態になっていました。
そこで引数を一回コピーして処理をしてみるとすべて正常に走ることができました!
協力してくださった皆さんにはとても感謝しております。
ご指導ありがとうございましたm(_ _)m
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:choconamacream /**
double配列の戻り値が欠落しないJavaプログラム
java version "1.5.0_18"

以下のサイトによると、「以前のバージョンの Java では」結果が異なることもあったらしいです。

http://java.sun.com/javase/ja/6/docs/ja/api/java/util/Random.html#n...

ただ、最新のJDKでも同じ症状だとすると、後はソースを提示してもらわないことには、いやはや何とも・・・。
*/
public class DoubleArray{
 double[] doubFuv;

 DoubleArray (double intpara){
  try{
   doubFuv = Hunx((int)intpara);
  }catch(NumberFormatException e){
   System.out.println("えらー、はっせい!!");
  }
 }

 double[] Hunx(int int_param){
  double[] rundi = new double[int_param];
  for (int i = 0; i < int_param; i++) {
   rundi[i] = Math.random();
   System.out.println("rundi[" + i + "]→" + rundi[i]);
  }
  return rundi;
 }

 public static void main(String[] args){
  DoubleArray da = new DoubleArray(5.0);
  int i = 0;
  for(double dF : da.doubFuv){
   System.out.println("doubFuv[" + i + "]→" + dF);
   ++i;
  }

 }
}
種類:アドバイス
どんな人:経験者
自信:自信あり
回答日時:09/10/20 01:18
回答番号:No.4
参考URL: http://www.techscore.com/tech/J2SE/Thread/5-2.html
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

良回答20pt

回答者:tgook 「戻り値に配列を返す」というのは記憶に無いため、「これが原因だ!」とは断言できませんが、参考URLの「戻り値として配列を返すメソッド」のコードと、No.1様のコードを比較すると、staticで宣言されたメソッドが、更にPublic宣言でされているか?というところが気になります。
staticの前にPublicを記述して再度試されてみては如何でしょうか?

また、printlnで配列に正常に値が入っているとありましたが、
return rundi;
の前で
System.out.println(rundi);
は試してみましたか?
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:09/10/19 19:53
回答番号:No.3
参考URL: http://d.hatena.ne.jp/nekochan_mama/20081016/1224160636
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:Tacosan たぶん私では役に立たないと思いますが, 可能ならその問題が発生する簡単なコードを出してもらえないでしょうか?
種類:補足要求
どんな人:一般人
自信:参考意見
回答日時:09/10/19 12:07
回答番号:No.2
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:pribaoutki 謎です・・・

static double[] Hunx(int intpara) {
  double[] rundi = new double[intpara];
  for (int i = 0; i < intpara; i++) {
    rundi[i] = Math.random();
  }
  return rundi;
}
のようにメソッド定義して、
double[] doubFuv = Hunx((int)intpara);
と呼び出しているということでしょうか?

だとすると、ロックするまでもなく、他のスレッドからdouble配列をいじることは不可能です。(意図的に他のスレッドに受け渡す前の時点では)
double配列はメソッド内でもメソッド外でもローカル変数ですから。

「printlnして実行を確認」この確認部分がバグっている可能性はありませんか?
欠落していない箇所はメソッド内外で同じ値を保っていますか?
乱数ではなく規則的な数列、たとえば 0,1,2・・・という連番を入れたらどうなりますか? というか規則的な数列を入れたほうがデバッグしやすいと思います。
種類:アドバイス
どんな人:専門家
自信:参考意見
回答日時:09/10/19 02:25
回答番号:No.1
この回答への補足まさにそのプログラムのままです。
私もなぜこのようなことが起こるのか不思議でなりません、、、
環境はMac os x gccとなんら変わらない環境で、一回メモリ関連かとも思い再起動も何回も試しましたが一向に治りません。

欠落する数値も不規則で、法則もありませんでした・・・。
配列生成のメソッドでのforeachをかけた時の配列は正常
0.23462474245
0.72462346246
0.62462534566
0.23463464636
配列を受け取った側(Mainなど)
0.0
0.72462346246
0.62462534566
0.0
といった感じになります。
この0.0は表示不良でもなく、配列にしっかり0.0と入っていて、本当に謎です
この回答へのお礼この回答にお礼をつける(質問者のみ)
最新から表示回答順に表示良回答のみ表示