【最大10000ポイント】当たる!!質問投稿キャンペーン!

for (i = N - 1; i >= 0; i--) {
a[i][N] /= a[i][i];
for (j = i + 1; j < N; j++)
a[i][N] -= a[i][j] * a[j][N] / a[i][i];
}
のプログラムを
for (i = N - 1; i >= 0; i--) {
  d = a[i][N]/ a[i][i];
  for (j = i + 1; j < N; j++)
    a[i][N] = d- a[i][j] * a[j][N] / a[i][i];
}

と a[i][N]をdと置き換えたところ、計算結果の異なりました。
何故なのでしょうか?
理由を詳しく説明して頂けると大変有り難いです。
また、どうしたらdに置き換えたとしても正しい計算が行えるのかを詳しく説明して頂けると有り難いです。
どうかよろしくお願い致します。

A 回答 (5件)

for (i = N - 1; i >= 0; i--) {


d = a[i][N]/ a[i][i];
for (j = i + 1; j < N; j++)
a[i][N] = d- a[i][j] * a[j][N] / a[i][i];
}

ではなくて

for (i = N - 1; i >= 0; i--) {
d = a[i][N]/ a[i][i];
for (j = i + 1; j < N; j++)
d -= a[i][j] * a[j][N] / a[i][i];
a[i][N]=d;
}

この計算順だと、dを使う意味無いですけどね。

ひょっとして -= 演算子の意味がわかってない?
    • good
    • 1

#3です。



>1回週のdで固定してしまったため、
一回週のdにはi=2のが入りそのままとなったので、2週目のdにも1週目と同じdが入る。なので、間違った計算になるという事でしょうか?

i=2とは限りませんが上記の理解でよい。
    • good
    • 0

内側のループの1回目終了後ではa[i][N]の値は同じ値になります。


なぜならループ内の式を実行する前の段階で上のコードでのa[i][N]と下のコードでのdの値が等しいので式の値は一致します。

ただし、2回目以降は異なります。
なぜなら2回目にループに入る直線の段階で上のコードでのa[i][N]と下のコードでのdの値は異なるため式が同じ値にならないのです。
dの値を変える式は存在しないため、何回目のループであろうともdの値は変化しません。

下の式をあえてdを使うコードに替えるには二通りの方法があります。
1.内側のループの最後に次の式を追加する。
d = a[i][N];

2.dをポインタとして定義してdの示すアドレスをa[i][N]のアドレスにしてしまう。
dをポインタとして宣言(たとえば int *d;)して、最初のループの頭に
d = &a[i][N];
としてポインタ変数dにa[i][N]のアドレスを代入します。そうすると以降*dはa[i][N]の値を返すようになります。
以降の式はdを*dに置き換えれば意図したように動くはずです。
    • good
    • 0
この回答へのお礼

1回週のdで固定してしまったため、
一回週のdにはi=2のが入りそのままとなったので、2週目のdにも1週目と同じdが入る。なので、間違った計算になるという事でしょうか?

お礼日時:2018/08/03 18:43

No.1です。


お礼の文章ですが、適度な改行や空行を入れて、他の人が読みやすいかどうかを気にしていただけますと嬉しいです。


閑話休題

> dではなく、なぜa[i][N]だと正しく代入され、置き換えたdでは正しく代入されないのでしょうか?

a[i][N] = d- a[i][j] * a[j][N] / a[i][i]

において質問者様は、置き換えたdのことばかり気にされているようです。
問題はdではなく、a[j][N]の値にあることをNo.1で回答しました。

もう一度、時間をかけてよく読んで内容を理解してください。
また、aの配列の値について二次元の表を紙(やエクセル)に書いて、dを使用した場合と使用しない場合で、二重のforループでの表中の各値がどのように変化していくかを手(電卓)計算すれば、より理解が深まると思います。
    • good
    • 0
この回答へのお礼

だとしたら、元のプログラム
for (i = N - 1; i >= 0; i--) {
d = a[i][N];
for (j = i + 1; j < N; j++)
d -= a[i][j] * a[j][N];
a[i][N] = d / a[i][i];
}
はdを使っていますが、なぜdが1週目で固定されないのでしょうか?
最後にa[i][N] = d / a[i][i];があるためですか?

お礼日時:2018/08/03 19:21

Nは定数と仮定して。


外側のforでi=1の時を考えます。

 a[1][N] /= a[1][1];
  ↓
 d = a[1][N]/ a[1][1];

と変更したので
この行が実行された段階でa[1][N]には正しい値が代入されておりません。


次に外側のforでi=0のループに変わります。
このとき内側のforの最初のループではj=i+1(=1)となるので。
内側のforの中にある式は

 a[0][N] = d- a[0][1] * a[1][N] / a[0][0];

となりますが、式の中のa[1][N]には正しい値が入っていないので
結果、a[0][N]にも正しい計算結果が代入されないことになります。


ここまでi=1の場合で考えましたが、当然iが他の値でも同じことが起こります。



> また、どうしたらdに置き換えたとしても正しい計算が行えるのか

 d = a[i][N]/ a[i][i];
 ↓
 d = a[i][N]/ a[i][i];
 a[i][N] = d;

とするとか?
(詳しくみてないので、これでもダメかもしれません)
    • good
    • 0
この回答へのお礼

わかりやすい解答ありがとうございます。あのd = a[i][N]/ a[i][i]においてdとおきました。そしてa[i][N] = d- a[i][j] * a[j][N] / a[i][i]にd = a[i][N]/ a[i][i]を代入しようとa[i][N] = d- a[i][j] * a[j][N] / a[i][i]にdをつけたのですが、これではa[i][N] = d- a[i][j] * a[j][N] / a[i][i]のdにd = a[i][N]/ a[i][i]は代入されないのでしょうか?
dではなく、なぜa[i][N]だと正しく代入され、置き換えたdでは正しく代入されないのでしょうか?
どうかよろしくお願い致します。
二次元配列などと関係あるのでしょうか?

お礼日時:2018/08/03 05:56

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

このQ&Aと関連する良く見られている質問

QC言語の課題がわかりません char型変数をa個、int型変数をb個、double型変数を4個使うと

C言語の課題がわかりません

char型変数をa個、int型変数をb個、double型変数を4個使うとき、全部で何バイトのメモリを使うか求めるプログラムを作成せよ。なおa,bは実行中にキーボードから入力すること、また各データ型もしくは各変数のバイト数を求める際にはsizeof演算子を使うこと。

という問題なのですが、言っている意味も分からなければどのようなプログラムを書けばよいのかもわかりません。おしえてください

Aベストアンサー

『標準入力から』が正しい表現なんでしょうけど、初学者向けだとキーボードからと書かれる…でしょう。>#3


>またキーボードで入力するということはscanfを使うということなのでしょうか

scanf()だけとは限りませんけどね。
fgets()で取り込んで、数字→数値変換するとかありますし。
が、学校とかの課題レベルならscanf()辺りが妥当でしょう。
ろくにエラー処理してなくても合格もらえるんじゃないでしょうかね。

>変数の内容ではなく個数と書いてある点がよくわからなくて…

サイズ(バイト数)の計算に、個々の変数の内容は関係ないからです。
int型の変数に0が格納されているときと10000が格納されているときでメモリ上のサイズが変動したりはしません。

Qc言語の課題がわかりません

XOR を用いて文字列の暗号化及び暗号化された文字列の復号化をするプログラムを作成し,暗号化した文字列の結果は code.txt に出力し、復号化する際には code.txt からファイルを読み込んで復号化することとし、入力する文字列は最大で 9 文字までとする。暗号化および復号化には鍵として1つの文字用いる。鍵は暗号化の際に入力させ、復号化の際にも同じ鍵を用いる。暗号化は文字列の各文字ごとに鍵との間の XOR を取るものとする。と課題で出たのですが、自分には難しすぎて出来ません。どなたかおしえてください。プログラムの途中経過と実行例を記しておきます。
#include<stdio.h>
int main(){
int x;
char a[256],b[256];

printf("Select Mode 1.Encryption, 2.Decryption :");
scanf("%d",&x);
if(a==1){
printf("Input passphrase :");
scanf("%s",a);
printf("Input key:");
scanf("%d",b);
}else{
printf("Input key:");
scanf("%d",b);

}

if(a==3){
printf("Invalid value\n");
}
return 0;
}
<実行例 1>
Select Mode 1.Encryption, 2.Decryption : 1
Input passphrase : password
Input key : $
TEWWSKV@
<実行例 2>
Select Mode 1.Encryption, 2.Decryption : 2
Input key : $
Code : TEWWSKV@
Decode : password
<実行例 3>
Select Mode 1.Encryption, 2.Decryption : 3
Invalid value

XOR を用いて文字列の暗号化及び暗号化された文字列の復号化をするプログラムを作成し,暗号化した文字列の結果は code.txt に出力し、復号化する際には code.txt からファイルを読み込んで復号化することとし、入力する文字列は最大で 9 文字までとする。暗号化および復号化には鍵として1つの文字用いる。鍵は暗号化の際に入力させ、復号化の際にも同じ鍵を用いる。暗号化は文字列の各文字ごとに鍵との間の XOR を取るものとする。と課題で出たのですが、自分には難しすぎて出来ません。どなたかおしえてください...続きを読む

Aベストアンサー

以下、ファイルの入出力を絡めると理解が遠のくので、
シンプルに、画面を通しての入出力動作をするものにしました。
forループの中で行っている1行が最も重要な箇所なので、じっくり理解して下さい。

#include<stdio.h>
#include<string.h>

int main() {
int x;
char a[9+1];
char b[1+1];
char r[9+1];

memset(a, 0x00, sizeof(a));
memset(b, 0x00, sizeof(b));
memset(r, 0x00, sizeof(r));

printf("Select Mode 1.Encryption, 2.Decryption : ");
scanf_s("%d", &x);
if (x == 1) {

printf("Input passphrase : ");
scanf("%s", a);

printf("Input key: ");
scanf("%s", b);

} else if (x == 2) {
printf("Input key: ");
scanf("%s", b);

printf("Code : ");
scanf("%s", a);

printf("Decode : ");

} else {
printf("Invalid value\n");
return 0;
}

for (unsigned int i = 0; i < strlen(a); i++) {
r[i] = a[i] ^ b[0];
}

printf("%s\n", r);

return 0;
}

以下、ファイルの入出力を絡めると理解が遠のくので、
シンプルに、画面を通しての入出力動作をするものにしました。
forループの中で行っている1行が最も重要な箇所なので、じっくり理解して下さい。

#include<stdio.h>
#include<string.h>

int main() {
int x;
char a[9+1];
char b[1+1];
char r[9+1];

memset(a, 0x00, sizeof(a));
memset(b, 0x00, sizeof(b));
memset(r, 0x00, sizeof(r));

printf("Select Mode 1.Encryption, 2.Decryption : ");
scanf_s("%d", &x);
if (x == 1) {

printf(...続きを読む

Qsleep関数の原理について

sleep関数がPC内でどういった原理で一定時間おきに動作などを行っているのか教えてください。
「Linuxカーネルがどういう働きしている」「ハードがどういう動作している」とかです。

Aベストアンサー

>一定時間おきに動作などを行っているのか
確実にsleep関数で指定した時間はお休みしているだけであり、
厳密には「一定時間おき」に動作はしません。

・LinuxはマルチタスクOSである
・一定時間(確か100Hzだったと思います)ごとにタスク切り換えを行っている

この2点がわかっていれば、
>「Linuxカーネルがどういう働きしている」
は簡単ですよね。

「sleep関数で指定した時間は、タスク切り換えで自分にCPU時間を割り当てることはしない」というだけです。

>「ハードがどういう動作している」
特段ハードでは、sleep関数実現のために何もしていません。

<おまけ>
sleep関数を呼ばなくてもマルチタスクOS上のタスクは、
 ユーザの知らないタイミングで休み休み動いている
ということです。

Qscanfが動きません。どうしたら良いですか

環境
msys2, mintty, bash, gcc8.2.0

ソースコード
#include <stdio.h>
int main(){
unsigned char a, b;
printf("a = "); fflush(stdout); scanf("%d", &a);
printf("b = "); fflush(stdout); scanf("%d", &b);
printf("a = %d, b = %d", a, b);
return 0;
}

実行結果
(入力はa=5, b=10とします)
a = 0, b = 10

ソースの間違いの他には端末の設定とかインストールのミスを疑っています。解決方法を知っている方教えてください。ただしコンパイラを変えることはできません。

Aベストアンサー

scanf で、書式%dはintのサイズの領域に入力を格納する。
領域サイズが足りていないと予測し難いことが起きる。

QC言語でプログラミングを組みたいんですがcosの使い方がわかりません

x_i = cos((pi*(2i-1))/2N) (i=1,2,…,N)

という式で、N=5,9,17の時の値を求めたいのですが、うまくできません。

頑張ってN=5の式を作ってみたのですがうまくいきませんでした。
C言語、プログラミング初心者でわからないのでできるだけ丁寧に教えていただけると助かります。

自分で作ってみたプログラムを書いてみたので、どこが違うか、またどうすればいいかを教えていただきたいです。



#include <stdio.h>
#include <math.h>

#define iMAX 5

#define PI 3.1415926535


int main()
{

int i ;

int x[iMAX] ;

int n = ((PI * (2i-1) ) / 10) ;

double cos ( n ) ;



for (i = 1; i < 5; i++) {

x[i] = cos ( n );

}


for (i = 1; i<=5; i++) {

printf("x[%d] = %d\n",i,x[i]);

}


return 0 ;


}

x_i = cos((pi*(2i-1))/2N) (i=1,2,…,N)

という式で、N=5,9,17の時の値を求めたいのですが、うまくできません。

頑張ってN=5の式を作ってみたのですがうまくいきませんでした。
C言語、プログラミング初心者でわからないのでできるだけ丁寧に教えていただけると助かります。

自分で作ってみたプログラムを書いてみたので、どこが違うか、またどうすればいいかを教えていただきたいです。



#include <stdio.h>
#include <math.h>

#define iMAX 5

#define PI 3.1415926535


i...続きを読む

Aベストアンサー

cosの結果はdouble型です。
x_i = cos((pi*(2i-1))/2N) は、コード上、正確には
x_i = cos((pi*(2*i-1))/(2*N)) です。
N=5の場合、iを1からNまで変化させればOKです。
以下のようにしてください。
#include <stdio.h>
#include <math.h>
#define N 5
#define PI 3.1415926535
int main()
{

int i;
double x_i;
for (i = 1; i <= N; i++) {
x_i = cos((PI*(2*i-1))/(2*N));
printf("x[%d] = %f\n",i,x_i);
}
return 0;
}
-----------------------
以下、実行結果です。
x[1] = 0.951057
x[2] = 0.587785
x[3] = 0.000000
x[4] = -0.587785
x[5] = -0.951057

cosの結果はdouble型です。
x_i = cos((pi*(2i-1))/2N) は、コード上、正確には
x_i = cos((pi*(2*i-1))/(2*N)) です。
N=5の場合、iを1からNまで変化させればOKです。
以下のようにしてください。
#include <stdio.h>
#include <math.h>
#define N 5
#define PI 3.1415926535
int main()
{

int i;
double x_i;
for (i = 1; i <= N; i++) {
x_i = cos((PI*(2*i-1))/(2*N));
printf("x[%d] = %f\n",i,x_i);
}
return 0;
}
-----------------------
以下、実行結果です。
x[...続きを読む

QC言語でWEbアプリが作れますか?

C言語はあらゆるアプリの基礎と成っているのに、WEbアプリを作ろうとしても、どうすればよいか?わかりません。また、WEbアプリをC言語で開発する本も売ってない。なぜだろう

Aベストアンサー

C/C++言語によるCGIプログラミングの設計入門
http://www-cms.phys.s.u-tokyo.ac.jp/~naoki/CIPINTRO/CCGI/

C言語はネットワーク向きとは思いません。
 ネットワーク関連なら今の時代、なにかしらのフレームワークを使うのではないだろうか。

QCのif文の書き方の質問です

『x=a & j=1 』の様に、『&』の前後に式を書くことがありますか?
使ったことがないので、ここに質問させて頂いております。
コメント、説明頂けますと大変有り難いです。

if stype=='L' then
x=a & j=1 //===
elseif stype=='M' then
x=a+(h/2) & j=2//============
else x=a+h & j=3//=================
end

以上、宜しくお願いします。

Aベストアンサー

見た目から、命令の区切りに使っているように見えますが、
公式マニュアルを確認しても ; や , はありましたが & は見つけられなかったので断言はできません。

https://help.scilab.org/docs/6.0.1/ja_JP/comma.html
https://help.scilab.org/docs/6.0.1/ja_JP/semicolon.html

QPIC12F683から移植

PIC12F683のコードをPIC16F1827移植しようと思い
以前作ったコードを眺めていたら、下記のコードのコメントをしていなく
しばらくPICを触っていなかったのもあり
GPIFとGPIEの所で混乱中です。
コンパイラは、XC8 1.45です。
16F1827ではどの様に記述したら良かったでしょうか
IOCは、IOCAFの事だと思いますがよろしくお願いします。

IOC = 0b00110000; //割込み有効入力 GP4,GP5
GPIF = 0;
GPIE = 0;

Aベストアンサー

PIC12F683→PIC16F1827に移植した場合

<12F683>IOC(ピン変化割込み検出有効化)
        ↓
<16F1827>IOCBP(ピン変化割込み立ち上がり検出有効化)
      IOCBN(ピン変化割込み立ち下り検出有効化)

<12F683>GPIF(変化割込みフラグ)→<16F1827>IOCIF(変化割込みフラグ)

<12F683>GPIE(変化割込み制御)→<16F1827>IOCIE(変化割込み制御)

となり、16F1827移植した場合

//====ここから====
IOCBP = 0b00110000; //立ち上がり割込み有効入力 GP4,GP5
IOCBN = 0b00110000; //立ち下り割込み有効入力 GP4,GP5
IOCIF = 0; //変化割込みフラグビット(1:許可 0:禁止)
IOCIE = 0; //変化割込み制御ビット(1:変化あり 0:変化なし)
//====ここまで====

上記のようになるかと思います。
又、IOCxFレジスタ("x"は16f1827の場合は"B")は変化割込みフラグレジスタになります。

PIC12F683→PIC16F1827に移植した場合

<12F683>IOC(ピン変化割込み検出有効化)
        ↓
<16F1827>IOCBP(ピン変化割込み立ち上がり検出有効化)
      IOCBN(ピン変化割込み立ち下り検出有効化)

<12F683>GPIF(変化割込みフラグ)→<16F1827>IOCIF(変化割込みフラグ)

<12F683>GPIE(変化割込み制御)→<16F1827>IOCIE(変化割込み制御)

となり、16F1827移植した場合

//====ここから====
IOCBP = 0b00110000; //立ち上がり割込み有効入力 GP4,GP5
IOCBN = 0b00110000; //立ち下り割込み有効入力 GP4...続きを読む

QC言語でエラーの直し方が分かりません。

x_i = cos ((PI*(2*i-1))/( 2*N )) i =1,2,...,N   (見づらくてすみません)

という式を計算して、結果を出力したいのですが、コンパイルできません。
自分で書いてみたプログラムとエラーを書いておくので、どこを直せばいいか教えてください。

#include <stdio.h>
#include <math.h>

#define PI 3.1415926535

double x_i(int i, int N)
{
for (i = 1 ; i <= N ; i++) {
x_i(i, N) = cos ((PI*(2*i-1))/( 2*N ));

}
}

int main()
{
int i, N ;
printf("N= ");
scanf("%d", &N);
for (i = 1 ; i <= N ; i++) {

printf("x[%2d] = %f\n",i, x_i(i,N));

}

return 0 ;
}


C:\Users>gcc nnn.c
nnn.c: In function 'x_i':
nnn.c:9:16: error: lvalue required as left operand of assignment
x_i(i, N) = cos ((PI*(2*i-1))/( 2*N ));
^


初心者なのでできれば丁寧に教えていただけると助かります。
よろしくお願いします。
結果は、
C:\Users>a
N = 5
x[ 1] = 0.951057
x[ 2] = 0.587785
x[ 3] = 0.000000
x[ 4] = -0.587785
x[ 5] = -0.951057

という風にしたいです。

x_i = cos ((PI*(2*i-1))/( 2*N )) i =1,2,...,N   (見づらくてすみません)

という式を計算して、結果を出力したいのですが、コンパイルできません。
自分で書いてみたプログラムとエラーを書いておくので、どこを直せばいいか教えてください。

#include <stdio.h>
#include <math.h>

#define PI 3.1415926535

double x_i(int i, int N)
{
for (i = 1 ; i <= N ; i++) {
x_i(i, N) = cos ((PI*(2*i-1))/( 2*N ));

}
}

int main()
{
int i,...続きを読む

Aベストアンサー

>以下のプログラムで正常に動いたので、これを関数に変えればいいと思っていたのですが、うまくいかず質問させていただいてるという流れです。

・ループはコール側でやっているので関数内でやる必要はない。
・ループで結果を表示しているので配列は関係ない。
ということで…

>double x_i(int i, int N)
>{
> for (i = 1 ; i <= N ; i++) {
>  x_i(i, N) = cos ((PI*(2*i-1))/( 2*N ));
> }
>}

は、
double x_i(int i, int N)
{
 return cos ((PI*(2*i-1))/( 2*N ));
}
になるだけなんじゃないですかね?


>int i[20];   //配列の指定の大きさ
>int N[20];
で、関数の方は
>double x_i(int i, int N)
で、コールは
>printf("x[%2d] = %f\n",i, x_i(i,N));

コールする時の第1引数と第2引数は配列を渡していますが、関数の仮引数の方と一致しません。
ということで、コンパイルエラーでしょう。

>x_i(i, N) = cos ((PI*(2*i-1))/( 2*N ));

既に指摘していますし、他の方からも回答ありますが、関数コールに対して値の代入はできません。
ので、こちらもコンパイルエラーでしょう。


>Nは5と決まっているわけではなくて、20までで自分で、自由に決めれるようにしたいです。

>printf("i = ");
>scanf("%d", &N);

iなのかNなのか不明ですが…
規定の範囲の値が入力されるまでループするようにすればよいかと。

do {
 printf("i = ");
 scanf("%d", &N);
} while((N < 0) || (N > 20));
とか?
# scanf()でのエラー処理していませんが。(数字以外を入力すると無限ループに堕ちるとか)

>以下のプログラムで正常に動いたので、これを関数に変えればいいと思っていたのですが、うまくいかず質問させていただいてるという流れです。

・ループはコール側でやっているので関数内でやる必要はない。
・ループで結果を表示しているので配列は関係ない。
ということで…

>double x_i(int i, int N)
>{
> for (i = 1 ; i <= N ; i++) {
>  x_i(i, N) = cos ((PI*(2*i-1))/( 2*N ));
> }
>}

は、
double x_i(int i, int N)
{
 return cos ((PI*(2*i-1))/( 2*N ));
}
になるだけなんじゃないですかね?
...続きを読む

Qc言語について

このプログラムは(ありがとう)を5回入力するのですが、n<5だと4回しか表示されないと思うのですが、どうなんでしょうか。

Aベストアンサー

forループの1回目のnの値は0なのでprint文を実行。
2回目は1なのでprint文を実行。
3回目は2なのでprint文を実行。
4回目は3なのでprint文を実行。
5回目は4なのでprint文を実行。
6回目は5なのでループを抜ける。

参考まで。


[おまけ]
print文の次の行の}はforの下に来るようにした方が可読性が高いです。
同様にreturn文の次の行の}は3行目の{と同じ位置にした方が可読性が高いです。
そうすると全体として{から}までの範囲を直観的に理解できてソースコードを読むのが楽になります。


人気Q&Aランキング