質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.39%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

393閲覧

行列を作るとき、行列の成分を[0,1)上の乱数としたいです。

nekopota.

総合スコア22

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2023/12/29 09:03

実現したいこと

100 種類の連立一次方程式 Ai*x = bi, i = 1, 2, . . . , 100 を単純 Gauss の消去法で解き,得られた近似解 xi に対する残差 2 ノルム ∥bi − Aixi∥2 や計算時間を求めたいです。このとき、行列サイズは 5 × 5とし,成分は右辺項も含めてすべて [0, 1) 上の乱数にしたいです。

発生している問題・分からないこと

自分が作ったコードはエラーが出ずに動くのですが、[0,1)上の乱数になっているのかがよくわかりませんでした。これは正しく実装できているのでしょうか。c++ではRAND_MAXを使うと[0,1)の範囲にならないという記事を見たのですが、改善の仕方がわかりません。また、この実装は1回しか行われないのですが、100種類調べたいので本当は100回繰り返したいです。どのように書けば良いのでしょうか。ご教示いただきたいです。よろしくお願いいたします。

該当のソースコード

c++

1//Gauss-消去法(帯行列、大きいサイズ) 2 3#include <math.h> 4#include <stdio.h> 5#include <iostream> 6#include "LinearAlgebra.hpp" 7 8int main(){ 9 //ここでAとbどんなものか書く 10 vector<vector<double> >A(5,vector<double>(5)); 11 vector<double> b(5); 12 //vector<double> x(5); 13 14 for(int i=0;i<5;i++){ 15 for(int j=0;j<5;j++){ 16 A[i][j]=(double)rand()/RAND_MAX; 17 } 18 b[i]=(double)rand()/RAND_MAX; 19 } 20 21 //行列Aを表示 22 cout<<"A="<<endl; 23 printMatrix(A); 24 25 //ベクトルbを表示 26 cout<<"b="<<endl; 27 printVector(b); 28 29 //前身消去した後のAとbを表示 30 vector<double> x(5); 31 32 x = GaussianElimination(A,b); 33 34 //後退代入過程を用いた解xを表示 35 cout<<"x="<<endl; 36 printVector(x); 37}

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

RAND_MAXを消すと[0,1)上になりませんでした。

補足

特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hiroki-o

2023/12/29 17:03

確かに、ちょうどになるパターンを忘れていた...どちらにしてもstd::generate_canonicalを使えばいいですね。
jbpb0

2023/12/30 09:22

質問者さん > エディタmiを使って 「mi」 https://www.mimikaki.net/ を使ってるならmacでしょうから、コンパイラは、xcodeのclangか、brewで入れたgccか、そのあたりですかね > unknown type name 'constexpr' コンパイル時のコンパイラのオプションに 「-std=c++11」 を付けてみてください 参考 https://stackoverflow.com/questions/45047508/error-unknown-type-name-constexpr-during-make-in-mac-os-x https://github.com/tesseract-ocr/tesseract/issues/3295
nekopota.

2023/12/30 11:48

回答ありがとうございます。 コンパイル時のコンパイラとはどのことでしょうか。教えていただきたいです。
nekopota.

2023/12/30 11:53

できました!!!ありがとうございます。 1つ質問なのですが g++ -c mainn.cpp -o mainn.out //g++ -c LinearAlgebra.cpp -o LinearAlgebra.out //g++ mainn.out LinearAlgebra.out ./a.out とうって実行しているのですが、4つ全ての後ろに-std=c++11がいるのでしょうか。どれかにつければいいのでしょうか。
hiroki-o

2023/12/30 13:12

LinearAlgebra.cppが何だかわかりませんが、2行目と3行目のコメントを外して、1~3行目ともに-std=c++11を付けて、私が最初に提示したC++の方法を試してみてほしいです。 それで上手くいったら、評価をお願いします。 上手くいかなかったら、エラーメッセージを貼ってください。勉強になるので。
nekopota.

2023/12/30 15:22

うまくいきました。ありがとうございます。本当に助かりました。
jbpb0

2023/12/30 16:59

> 4つ全ての後ろに-std=c++11がいるのでしょうか。 この質問の「該当のソースコード」が「mainn.cpp」で、hiroki-oさんの回答の最初の(「constexpr」とかが有る)コードのように変更するのなら、 g++ -std=c++11 -c mainn.cpp -o mainn.out とします g++ -c LinearAlgebra.cpp -o LinearAlgebra.out にも同様に「-std=c++11」を付ける必要が有るかは、「LinearAlgebra.cpp」の内容次第ですので、まずは付けずに実行してみて、エラーが出たら付けて実行してみてください g++ mainn.out LinearAlgebra.out ./a.out には付ける必要は無いと思います
yohhoy

2024/01/25 01:07

「-std=c++11」オプションのように言語バージョンを指定する場合、無用なトラブルを防ぐためにプロジェクト内の全 g++ コマンドに指定したほうが良いです。 (C++標準ライブラリ内でコード分岐している可能性があり、不統一状態でコンパイルされたオブジェクトファイル群をリンクするときにABI不一致を引き起こすことがあります)
guest

回答1

0

ベストアンサー

確認環境

  • Windows 11、Visual Studio 2022
  • FreeBSD 13.2、clang++ 14.0.5
  • Ubuntu 22.04.3、g++ 11.4.0

randは処理系により0~32767、または、0~2147483647を返す関数です。
RAND_MAXは、前者では32767、後者では2147483647と定義されているので、(double)rand()/RAND_MAXは[0,1)上の乱数になります。
ただし、疑似乱数なので、実際はsrandで乱数のタネを与えて使用します。

c++ではRAND_MAXを使うと[0,1)の範囲にならないという記事を見た

URLを教えてください。

C++で[0,1)上の乱数を発生させるには、std::generate_canonicalを使用します。

参考
https://cpprefjp.github.io/reference/random/generate_canonical.html

// 1行追加 #include <random> int main(){ //ここでAとbどんなものか書く std::vector<std::vector<double>> A(5,std::vector<double>(5)); std::vector<double> b(5); //vector<double> x(5); // 3行追加 std::random_device seed_gen; std::mt19937 engine(seed_gen()); constexpr std::size_t bits = std::numeric_limits<double>::digits; for(int i=0;i<5;i++){ for(int j=0;j<5;j++){ // 1行変更 A[i][j]=std::generate_canonical<double, bits>(engine); } // 1行変更 b[i]=std::generate_canonical<double, bits>(engine); }

100回繰り返したいなら、外側に100回繰り返すfor文を追加します。

(追記)
C++11以降に対応していない環境用

// 1行追加 srand(time(nullptr)); for(int i=0;i<5;i++){ for(int j=0;j<5;j++){ // 1行変更 A[i][j]=rand()/(RAND_MAX + 1.0); } // 1行変更 b[i]=rand()/(RAND_MAX + 1.0); }

投稿2023/12/29 16:39

編集2023/12/30 06:52
hiroki-o

総合スコア896

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hiroki-o

2023/12/30 03:38 編集

環境を具体的に教えてください。そして、エラーメッセージを提示してください。C++11以降に対応しているのなら、間違いなく使えるはずです。 (追記) リンク先の記事は、「よくある間違い」とあるように、間違った使用例です。RAND_MAXはrand関数と組み合わせて使用するものです。
nekopota.

2023/12/30 03:48

エディタmiを使っており、バージョンが3.7.7で最新のものと表示されます。 実行するとターミナル上に5このエラーがあると表示され、 unknown type name 'constexpr' definition or redeclaration of 'size_t' not allowed inside a function no member named 'size_t' in namespace 'std' expected ';' at end of declaration use of undeclared identifier 'bits' です。それぞれのエラーメッセージを調べ、改善しようと試みたのですが、うまくいきませんでした。 お手数おかけして申し訳ないです。よろしくお願いします。
hiroki-o

2023/12/30 06:54 編集

エディタではなく、コンパイラが何か知りたいのですが... もともとの#include文を消さずに#include <random>を追加したなら、そのエラーは出ないはずです。 いまどき、C++11以降に対応していないC++コンパイラを使用しているとは考えづらいですが、どうしてもコンパイラとそのバージョンを提示するのは無理ですか? コンパイル時に叩いているコマンドを、貼り付けるだけでもいいです。 (追記) 回答に追記しました。どうしても開発環境を提示できないなら、この方法でも実用上の問題は無いはずです。
nekopota.

2023/12/30 11:38

最近授業でプログラミングを始めたばかりでコンパイラとバージョンが今何になっているのか分からないです。申し訳ありません。 // 3行追加 std::random_device seed_gen; std::mt19937 engine(seed_gen()); constexpr std::size_t bits = std::numeric_limits<double>::digits; の部分を消し、追記していただいたものに変更したら実行することができました。何度もありがとうございます。 知識がなく、ご迷惑をおかけしてしまい申し訳ありませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.39%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問