2018-04-29 18:16:59 (6 years ago)
条件に応じてルートを変える二つの構文をまとめました。この二つの構文は、本当にキャラがかぶっていて憎らしいほどややこしい。個人的にはifの方がわかりやすいかなあ。
参考文献:高橋麻奈著『やさしいC第5版』
if文
もし○○だったら・・・という条件を与えて、その条件のもと真偽を判定する文。
今までのコードは、各行のおしりにセミコロン;を付けることが多かったが、なぜかif分のおしりにはセミコロン;をつけない。超トラップ。
60点以上なら合格、60点未満なら不合格と判定するコード
if文のところだけはセミコロンをつけないようにする。
#include
int main(void) {
int score;
printf("点数を入力\n");
scanf("%d",&score);
if(score>=60)
printf("合格");
if(score<60)
printf("不合格");
return 0;
}
入力された整数が偶数か奇数かを判定するコード
2で割った余りが0か1かで判断する。パリティピーポー(※3度目)。
#include
int main(void)
{
int num;
printf("整数を入力\n");
scanf("%d", &num);
if(num%2==1)
printf("%dは奇数です\n",num);
if(num%2==0)
printf("%dは偶数です\n",num);
return 0;
}
入れ子(ネスト)構造のif文
イメージとしては二次試験まである感じ。対象を絞り込む事が出来る。
授業の例だと、男性の大人だけ持ち物に髭剃りが追加されるようになっている。
#include
int main(void) {
int gender,age;
printf("性別を整数で入力(男:1,女:2): ");
scanf("%d",&gender);
printf("年齢を入力: ");
scanf("%d",&age);
printf("持ち物は着替えハブラシ");
if (gender==1) {
if (age>=20) {
printf("髭剃り");
}
}
printf("です.\n");
return 0;
}
入力された整数を分類するコード
「3の倍数」「3の倍数+1」「3の倍数+2」の3パターンに分類するためには、入力された整数を3で割って、その余り(懐かしのモジュラス)で判断するようにすればいい。
このコードも入れ子構造になっているのに注意。
まず、モジュラスを定義する大きな{}の中に、3つの{}(余り0の場合と、余り1の場合と、余り2の場合)が入っているようにしないとコンパイルできない(数学と違ってブロックの区切りがすべて中かっこなのでややこしい)。
そして、そもそも3で割れない場合(整数が3未満)はelse文ではじいている。
#include
int main(void) {
int n;
int mod;
scanf("%d", &n);
if (n > 2)
{
mod = n % 3;
if (mod == 0)
{ printf("%dは3の倍数\n", n); }
else if (mod == 1)
{ printf("%dは3の倍数+1\n", n); }
else if (mod == 2)
{ printf("%dは3の倍数+2\n", n); }
}
else
{
printf("%dは3未満\n",n);
}
return 0;
}
テストの点数によって成績をつけるコード
まず100点満点のテストなので点数がマイナスだったり100点を超える場合はエラーとする。
そのあと優>良>可>不可の順にelse if文でマトリョーシカ的に削ぎ落としていく。
#include
int main(void)
{
int n; //点数(数字)の変数を宣言
char *c; //成績(文字)の変数を宣言
scanf("%d", &n);
if(0>n || n>100) printf("\n入力エラー\n"); //ありえない点数
else{
if(n>=80)c="優"; //80点以上
else if(n>=65)c="良"; //65点以上80点未満
else if(n>=50)c="可"; //50点以上65点未満
else c="不可"; //50点未満
printf("\n成績:%s\n",c);
}
return 0;
}
善玉と悪玉のコレステロールの値を判定するコード
善玉コレステロールの正常値は 40以上、悪玉コレステロールの正常値は 70以上 140以下らしい。ちなみに私のコレステロール値はどちらも少ない。それはそれでどうなのだろうか。
#include
int main(void)
{
int zen,aku;
printf("善玉コレステロールの値を入力");
scanf("%d",&zen);
if(40<=zen)
{printf("善玉コレステロールは正常です。\n");}
else
{printf("善玉コレステロールは異常です。\n");}
printf("悪玉コレステロールの値を入力: ");
scanf("%d",&aku);
if(aku>=70 && aku<=140)
{printf("悪玉コレステロールは正常です。\n");}
else
{printf("悪玉コレステロールは異常です。\n");}
return 0;
}
switch文
if文と同じように、条件によって処理をコントロールできる文。
複数のケース(case)を任意に設定し、それ以外の入力があった場合はデフォルトということで、その他の処理としてまとめることができる。
注意点としては、case文ではセミコロン;ではなくコロン:をつけること、それぞれのケースのコードの最後にbreak;を入れないと、全ケースが表示されるバグが起きるということである。
年号をアルファベットから文字に変換するコード
M→明治、T→大正、S→昭和、H→平成に変換する設定。
#include
int main(void)
{
int res;
char ans;
printf("大文字のアルファベット一文字を入力\n");
scanf("%c", &res);
switch(res)
{
case 'M': //※セミコロンなのに注意!
printf("明治\n");
break; //※break文がないとバグるので注意!
case 'T':
printf("大正\n");
break;
case 'S':
printf("昭和\n");
break;
case 'H':
printf("平成\n");
break;
default: //どのケースにも当てはまらない場合
printf("エラー\n");
break;
}
return 0;
}
電卓のコード
数字1(num1)、演算子(op)、数字2(num2)の順に入力し、その計算結果(result)を返す。
#include
int main(void) {
int num1, num2, result;
char op;
printf("式:");
scanf ("%d %c %d", &num1, &op , &num2);
switch (op) {
case '+':
result = num1 + num2;
break;
case '-':
result = num1 - num2;
break;
case '*':
result = num1 * num2;
break;
case '/':
result = num1 / num2;
break;
case '%':
result = num1 % num2;
break;
default:
printf("エラー\n");
break;
}
printf("\n %d%c%dの結果:%d\n", num1,op,num2,result);
return 0;
}
入力された整数が偶数か奇数かを判定するコード(switch文バージョン)
2で割った余りが0か1かで判断する。パリティピーポー(※4度目)。
#include
int main(void)
{
int num,mod;
printf("整数を入力\n");
scanf("%d", &num);
mod=num%2;
switch (mod)
{
case 1:
printf("%dは、奇数です\n");
break;
case 0:
printf("%dは、偶数です\n");
break;
default:
printf("エラー\n");
break;
}
return 0;
}
整数を入力し、その値に対応する季節を表示するコード(caseのまとめ方)
3か4か5が入力されたら全部春と表示するというように、複数のケースをまとめたい場合は、単純に並べて書いちゃって大丈夫らしい。
#include
int main(void)
{
int num;
printf("整数:\n");
scanf("%d", &num);
switch(num)
{
case 3:
case 4:
case 5: //並べちゃうだけでコンパイルできる。
printf("春\n");
break; //※break文がないとバグるので注意!
case 6:
case 7:
case 8:
printf("夏\n");
break;
case 9:
case 10:
case 11:
printf("秋\n");
break;
case 12:
case 1:
case 2:
printf("冬\n");
break;
default: //どのケースにも当てはまらない場合
printf("?\n");
break;
}
return 0;
}
2018-04-28 11:49:17 (6 years ago)
ゴールデンウィーク突入!この千載一遇のチャンスでC言語を全クリする!!しかし、毎年思うんだけど、年度が始まってすぐ来るんだよな、ゴールデンウィーク・・・できればまだまだ頑張れるから、6月くらいまで繰り越しておきたいよね(^_^;)連休は超嬉しいけど、発進してすぐエンスト的な感じというか。だから5月病になるんだろうな(あと年度始めは学費払うから行楽にあてる金がない)。
いや、でもしっかり休むけどね。最近気温のアップダウンがえげつなかったし・・・
あ、あと今気づいたんだけど、ブログの仕様なのか、コード冒頭(include文)に必ず書かなければならない<stdio.h>が記事には表示されないので、本ブログのコードはその部分を書き足さないと機能しません!(´;ω;`)
参考文献:高橋麻奈著『やさしいC第5版』
式と演算
コンピュータは0で数字を割ると実行時にエラーとなりプログラムが停止するという最悪の事態になる。
四則演算の演算子は以下のとおり。
足し算:2+3 こたえ5
引き算:3-2 こたえ1
掛け算:2*2 こたえ4
割り算:6/3 こたえ2
割り算の余り:11%2 こたえ1
入力された二つの小数を使って四則演算するコード
小数なのでdouble型で宣言する。
入力時は%lfだが、出力時は小数点以下何桁まで出すか指定するのに注意(小数点以下3桁は%.3f)。
#include
int main(void)
{
double num1,num2,sum,hiku,kake,wari;
printf("実数1を入力\n");
scanf("%lf",&num1);
printf("実数2を入力\n");
scanf("%lf",&num2);
printf("%.3f+%.3f=%.3f\n",num1,num2,num1+num2);
printf("%.3f-%.3f=%.3f\n",num1,num2,num1-num2);
printf("%.3f*%.3f=%.3f\n",num1,num2,num1*num2);
printf("%.3f/%.3f=%.3f\n",num1,num2,num1/num2);
return 0;
}
三角形の面積を求めるコード
小数(厳密には浮動小数点数)の値で求めているので、変数はdoubleを用いる。
また小数を出力する場合は%dではなく、%fを用いる。
また%とfのあいだに.3などと数字を入れると、小数点以下3桁までで表示を打ち切ることができる。
#include
int main(void)
{
double teihen,takasa,menseki; //底辺、高さ、面積という3つの変数を宣言。
teihen=6.0;
takasa=3.0;
menseki=teihen*takasa/2; //数値、もしくは数式を代入。
printf("%f\n",menseki); // 出力。
return 0;
}
入力された半径から円の円周や面積を求めるコード
#include
int main(void) {
double r,c,s;
printf("円の半径を入力\n");
scanf("%lf",&r);
c=r*2*3.142;
printf("円 周=%.3f\n",c);
s=r*r*3.142;
printf("円の面積=%.3f\n",s);
return 0;
}
セルシウス温度をファーレンハイト温度に変換するコード
物理学概論が懐かしい・・・華氏(F)=(9÷5)×摂氏(C)+32なので・・・
#include
int main(void)
{
double C,F;
printf("摂氏を入力");
scanf("%lf",&C);
F=(9.0/5.0)*C+32.0;
printf("華氏になおすと%.2f",F);
return 0;
}
BMI指数を計算するコード
BMI=体重÷(身長×身長)であり、さらに身長はセンチではなくメートルに換算しないといけないため、単位を合わせるために分子を100×100倍する。
#include
int main(void)
{
double h,w,BMI;
printf("身長を入力\n");
scanf("%lf", &h);
printf("体重を入力\n");
scanf("%lf", &w);
BMI=w*10000/(h*h);
printf("%f\n",BMI);
return 0;
}
定期テストの平均点を求めるコード
テストの点数は整数(int型で宣言する)だが、平均点は小数(double型で宣言する)になるのでそこに注意する。
#include
int main(void)
{
int J,M,E,All;
double Av;
printf("国語の点数を入力\n");
scanf("%d", &J);
printf("数学の点数を入力\n");
scanf("%d", &M);
printf("英語の点数を入力\n");
scanf("%d", &E);
All=J+M+E;
printf("三科目合計=%d\n", All);
Av=All/3.0;
printf("三科目平均=%.2f\n",Av);
return 0;
}
2の平方根を計算する漸化式のコード
同じ計算を何度も繰り返すと、ちょっとずつ正確な値に収束していくタイプの計算。
Xに2を加えた数をXで割り、その数を更に2で割ることを繰り返すと、ヒトヨヒトヨニヒトミゴロに接近する。
#include
int main(void)
{
double x = 1.0;
x = (x + 2.0 / x) / 2.0;
printf("x=%.18f\n",x);
x = (x + 2.0 / x) / 2.0;
printf("x=%.18f\n",x);
x = (x + 2.0 / x) / 2.0;
printf("x=%.18f\n",x);
x = (x + 2.0 / x) / 2.0;
printf("x=%.18f\n",x);
x = (x + 2.0 / x) / 2.0;
printf("x=%.18f\n",x);
x = (x + 2.0 / x) / 2.0;
printf("x=%.18f\n",x);
return 0;
}
シフト演算子
ビットの桁の位置位置を左右にずらす(シフトする)ことができる演算子。
変数<<1 は変数を2倍(2の1乗)
変数<<3 は変数を8倍 (2の3乗)することができる。
#include
int main(void)
{
int num;
printf("整数を入力:");
scanf("%d", &num);
printf("入力値の10倍は:%d\n", (num<<1) + (num<<3));
// ※(num<<1)=2倍と(num<<3)=8倍を足して10倍にしている。
return 0;
}
ライフゲーム
イギリスの数学者コンウェイが1970年代に考案し、一時期流行ったシミュレーションプログラム。
オセロ盤のひとつのマスをセル(細胞)として、周囲のセルの状況によってそのセルの生死が決定するというルール。50行ほどの単純なコードだが、各セルは時間経過によってまるで生き物のようなアクティブな振る舞いをする。
命題
正しい(トゥルー)か誤り(フォールス)かが明確な文(平叙文)や式のこと。
日本の首都は東京である、みたいな○×クイズ的な文が命題と考えて良い。
疑問文や感嘆文、命令文といった曖昧な奴はダメ。
関係演算子
左辺と右辺の関係を表す演算子。
①== 左辺と右辺は等しい。
②!= 左辺と右辺は等しくない。
③> 左辺は右辺よりも大きい。
④>= 左辺は右辺よりも大きいか等しい。
⑤< 左辺は右辺よりも小さい。
⑥<= 左辺は右辺よりも小さいか等しい。
10+20は30かどうかを判定するコード
正しかったら1、誤りだったら0として表示される。
#include
int main(void) {
int i,j,k,l,m;
printf("整数iを入力\n");
scanf("%d" ,&i);
printf("整数iを入力\n");
scanf("%d" ,&j);
printf("整数iを入力\n");
scanf("%d" ,&k);
l=(i+j == k);
printf("条件式: 10+20 == 30 の値は%dです\n",l);
m=(i+j != k);
printf("条件式: 10+20 != 30 の値は%dです\n",m);
return 0;
}
2018-04-22 21:04:16 (6 years ago)
「面白い度☆☆☆☆☆ 好き度☆☆☆☆」
新聞記事は歴史書の最初の草稿だ。いい表現よね。
ナドレックさん激オシ映画。傑作・・・!これは今見るべき映画!
とにかく、メリル・ストリープの社主が凄いカッコいい!政府(主にニクソン)の圧力と同時に、当時の重苦しい男性社会と戦う映画になってるんだな。パターナリズムの怖さというか。
偉そうにする男どもにいじめられ続けてきた女性が最後にクリティカルアタックする爽快さ、というか。もちろん実話なんだけど、ちゃんとエンターテイメントになってるのが、毎度すごいよね。
この映画ってすごい突貫工事で作ったらしいんだけど、日米問わず本当にタイムリーだし(多くは言うまい)、かといって一過性なものじゃなくて普遍的なメッセージだし。すごい。
新聞の輪転機にも萌える映画!必見だ・・・!
この映画見てつくづく思ったのは、ニクソン閣下に限らず
自分個人に対する批判や疑問を、国家への侮辱だと卑劣にスライドさせるヤツは権力者に限らずわりといる(特に男にいる)ってことね。同一化というか。
私の経験上でも、だいたいろくでもない奴って身の丈以上のでかいことをうそぶくんだよ。
①この町が世界を変えるとか言う町会議員(世界がその町を相手にするとは思えない)。
②生徒のためとか言う教師(そういう教師はだいたい生徒に嫌われている)。
③外来種を駆逐して生態系を保全しろとか言う生き物マニア(人間が嫌いなだけ)。
だから、あれだ。こういうことは自分で自分に言い聞かせればいいわけで、
相手に強いることじゃないじゃん。強いている時点で、だいたい胡散臭いね。
この問題ってさ、アメリカ史だとけっこう有名な話でさ。
英米文学の記事と、かぶるんだけど、東大の佐々木毅先生の『民主主義という不思議な仕組み』(132ページから)にすごいわかりやすくまとめてあったから、ちょっと長いけど引用したい。
アメリカのマサチューセッツ州で、ヘンリー・デイヴィット・ソローというひとりの文筆家が、奴隷制反対などを楯にして、人頭税の納税拒否をいわば主義として宣言して投獄されました。(略)
この市民の服従拒否(civil disobedience)という発想は、やがて政治と向かい合う一つの態度として注目を集めるようになります。(略)
まず、彼は無政府主義者ではなく、政府は人間社会に必要な便宜を提供する機械、メカニズムであると考えています。そして、政府がこの便宜提供の役割に自分を限定し、個人を最高の価値のあるものとして、敬意をもって取り扱うようになることを自らの理想としています。問題は、政府の動向を支配する多数者が正、不正の判断にまで踏み込み、個人の良心に反することを法律という形にし、それに対する服従を市民の義務として求める場合です。(略)
ここに、良心と政治の確執と緊張は避けられないことになります。(略)
「自由の避難所」を謳い文句にした国家が、実際には国民の六分の一が奴隷であり、全土が軍隊の下に屈従させられている状況では、「誠実な人間が反逆し、革命を起こすべきとき」であると、ソローは断言します。一七七五年の独立の時には誰しもが革命のときであると語りましたが、ソローの時代にはほとんどの者が「今は、そういう事態ではない」と言っていました。しかし、ソローによれば今こそそういう事態、まさに緊急の事態なのです。
つまり、これこそが、後にガンジーやキング牧師に影響を与えた思想なんだけど、この映画でも「報道の自由を守るには報道するしかない」ってスピ社会派映画の常連のトム・ハンクスが言ってて、これは、大統領や官僚は国民にとって油断ならない敵でしかない!!とか、そういうことを言いたいんじゃなくて、やっぱりシステムとして一線引かないとおっかないぞっていう話よ。
多分さ、銭形のとっつぁんはルパンのこと好きだと思うんだよ。でも、泥棒となあなあになっちゃ公僕としてダメじゃん。
だから、この映画を見て(・・・いるのだろうか?)、マスコミは国民のために頑張ってくれる安倍さんや政権の足を引っ張っているとか、ただのマスコミの自己満足なだけとか、そういう感想を持つ人もいるんだけどさ、それとこれとは話が違うんだよ。
マスコミの書く事がくだらねえとか、低俗とか、ゴミとかそういう感想を持ったり、発信したりするのはいいんだよ(私もしばしば思うし)。しかし、私たちが意識的にならなければならないのは、だからといって報道の自由を権力者が一方的に制限しちゃうことが許されるならば、マスゴミ!とかSNSでツイートしている人たちの発言権すら奪われかねないという、もっと
メタ的な問題がそこにはあるということなんだよ。
つまり、ナショナリズムでも父権主義でも、逆に博愛主義とかグローバリズムとかでもいいけど、
不特定多数が該当しうる大きな思想を論じるときは、そういった視点を持たないと、足をすくわれるというか。
マスコミがダメだ!じゃなくて、実は○○新聞の何月何日のこの記者が書いた社説がムカついただけなんじゃないかっていう。
よく、個別的なケースなのに、大人はみんな嘘つきだ!とか、言う人いるじゃん。でも本当は、
その嫌な奴がたまたま大人だっただけで、一般化するんじゃねーよ小娘がって、
私はソフトバンクのCMの女子高生に言いたい。
ナイーブな奴が増えたのか、逆にナイーブな奴にも発言権が与えられたのかは、分からないけどね。
ニクソンはクソだ。新聞社を潰したがってる。
2018-04-21 23:57:54 (6 years ago)
人生初つくば!つーか、どことなく感じる
海浜幕張感・・・!いいな~こういう都市だって知ってたら、筑波大学行ってたぜ~(´;ω;`)
てことで、こしさんに誘われて、つくばにある国立科学博物館の分館みたいなところに行ってきたんだけど、この分館の収蔵庫がすごくて、収蔵している標本の数が300万点くらいあって、まあ
上野のかはく300軒分なんだけど、その関係者以外立ち入り禁止の収蔵庫に年に一日だけ入れるってことで参加してきました。燻蒸を控えたバックヤードツアーというか。
哺乳動物、植物、人骨、鉱物、海洋生物などの標本がズラーっとあって、中でも3Dプリンタは驚いたな。あれを使って、芸人の馬鹿よ貴方はみたいな学者さんが、収蔵庫の動物の剥製を縮小してフュギュアにしてたんだけど、あんなんやられちゃったら
海洋堂お手上げっていうか、これで作った模型をミュージアムショップで売れば、絶対ぼろ儲けだぜって思うよ。
あとは、研究棟みたいなところで、虫媒花の研究者さんとかが講義やってて聴いたりした。特にビカリアの専門家の人の話が面白かったな。
世の中にはビカリアに人生をかける人もいるのか、と(^_^;)
で、あの貝って熱帯のマングローブとかにいる貝に似ていて、だから日本も新生代の中新世くらいは熱帯だったんじゃないかって仮説を提唱している人なんだけど、まあそれは可能性は低いという
まさかのマッチポンプオチで、確かに緯度的に厳しいよな、とか。
今は熱帯のみにいる貝が、あの時代にはもうちょっと北進して、ニホンザルみたいに、ある程度寒い環境にも適応できたやつがいたんじゃないかな、とか。
で、ビカリアは、なんか大きく分けると、日本と韓国のやつら(ヨコヤマビカリア)と、東南アジアのやつ(ベルヌーイビカリア)の二大派閥に分かれるっぽくて、いくつかグループがあったんだったら、そういうのもいたんじゃないかとかね。
それと熱帯の昆虫の専門家の人がいて、いろいろ質問したんだけど、というか、基本的にここの施設の人は会話が好きというか、すごい素人にも親切に教えてくれて、メチャ勉強になるんだけど、それで、保全生態学とかでモヤモヤしているところ、もう全部聞いちゃえって聞いて、で、やっぱり自分の感覚でいいのかって、すっきりした。
よくある絶滅速度の計算なんかはやっぱり既成事実のように書いてあるけど、やっぱり勇み足で、あれって
緑地面積の減少率から出しているらしいんだ。だから仮に、完全に一様に生物種が分布してたら個体数減るだけだろっていう。恐竜時代の絶滅速度の信ぴょう性に関しては言わずもがな、と。
ただし、私って昆虫ってなんか寿命も短いし、子どももたくさん生むから、種分化の速度って早いと思ってたんだけど、一般的に昆虫の種が増えるのにかかる時間は数千年とか数万年で、まあ、ショウジョウバエみたいな例外(数十年で2~3種に増える)はいるらしいんだけど、それでも人間が環境破壊で滅ぼしてしまうと、とてもそれをカバーするほどの速さで種を増やすことは難しいっていう。つまり、生物多様性はやっぱり人間の干渉でかなりドラスティックに減らせるっていうのは、事実としてあるんだと。
あと、外来種のコーナーで、サソリとかクモとかの専門の人がいて、結局マスコミが大騒ぎしたセアカゴケグモは、もう西日本では完全に打ち解けた、とw確かに危ない毒グモだけど、日本にもスズメバチとかいるし、市民権得たみたいに言ってて、これも面白かった。
それと海洋生物のフロアで貝の先生がいたんだけど、貝の世界は本当に全貌が全然分かってなくて、
年間200種類も新種が見つかるらしい。だとしたら、新種を発見したい若手の人にとっちゃ、本当に宝の山っていうか。
まあ、貝に限らず、この手の陽の目の見ない、研究者が全然いない生物は山ほどあるんだよっておっしゃってました。
だから、結局のところ地球上に生物が何種類いるかは全く見当もつかないと。線虫なんかはいろんな昆虫の中にいて、それを引っ張り出して同定するとしたら、すごいことになるぞ、と。
最後に、このクソ暑い中、野外でイルカの解体ショー(病理解剖)とかも
すしざんまい的にやってたんだけど、こしさんは興味津々でずっと見てたけど、もうね、すごいくさいのよ。
ビーフジャーキーが濃縮して腐ったような匂いで、オレ、ここ数週間あのおつまみは食えないわ(^_^;)
オーシャンハンター。
ダライアスバーストアナザークロニクル。
2018-04-17 19:20:07 (6 years ago)
参考文献:電子学園出版局『情報処理基礎講座コンピュータシステムの基礎』
負数の表現方法
2進法で+-といった符号をつける方法には大きく2つのやり方がある。
①1の補数
先頭のビットを0なら+、1なら-と、符号ビットとして使用する。
さらに、負の数は正の数と0と1が反転した1の補数を用いる方法。
8ビットの場合は7ビット分が絶対値を表すので、-127~+127までの数が表現できる。
わかりやすいが、0の表現方法が+0(00000000)と-0(11111111)の二通りできてしまい、コンピュータにとっては演算が複雑になる。
②2の補数
0の表現方法は00000000だけに限り、11111111から-1とカウントする方法。つまり負の数の表現の幅は1の補数の時よりも1つ多くなる(8ビットの場合-128~+127までいける)。
2の補数とは、1の補数に1を足した数のこと。
例えば、01101011の1の補数は10010100だが、これに1を加えた10010101が2の補数となる。
同様に、0010の1の補数は1101、2の補数は繰り上がって1110である。
練習問題1
2の補数で負数を表現しているとき、あるレジスタに格納されている負の数χの絶対値を求めるにはどうすればいいか。
①χのビットの0と1を反転させて正の数にする。
②2の補数で負数を表現している場合、正の数は負の数よりも1少なくズレているので、その数に1を足す。
練習問題2
2の補数で負数を表現しているとき、8ビットの2進数10010011の絶対値はいくつか。
①先頭のビットが1なので、この数は負数である。
②0と1を反転させて正の数にする。01101100
③正の数は負の数よりも1少ないので、1を足して01101101にする。
④各桁を十進数になおして全て足す。
0+64+32+0+8+4+0+1=109
小数点の表現方法
二進法においては、やっぱり大きく2つの方法がある。
①固定小数点
小数点の位置を固定する方法。位置はコンピュータによって異なるが、最下位桁の次や、最上位桁とその次の桁の間に置くのが一般的。
②浮動小数点
小数に応じて、小数点の位置を臨機応変に変える方法。
具体的には、指数(10進数の場合は常用対数)を使って変える。小数点が右にずれる場合は+1乗、左にずれる場合は-1乗。
エクセス64方式では、最初の1ビットが符号、次の7ビットが小数点の位置、残りの24ビットで絶対値を表している。
誤差
コンピュータにおける小数の数値には制約がある。
まず、十進法の小数の中には2進数で表せないものがある。例えば、0.1は2進数では0.000110011・・・と無限小数(0011の循環小数)になってしまう。
しかし、コンピュータには使用できる桁数が決まっているため、どこかの位で四捨五入をしたり、切り捨てなければならない。このときできる誤差をまるめ誤差という。
小数がビットの桁数を越えてしまうことによって起きる誤差には他にも以下のようなものがある。
①オーバーフロー(桁あふれ)
演算結果の数値が大きすぎて、有限なビットの表現の最大値を超えてしまうこと。
これが原因で打ち上げたロケットが爆発したことがあるらしい。
②アンダーフロー(下位桁あふれ)
演算結果の数値が小さすぎて、有限なビットの表現の最小値を超えてしまうこと。
③桁落ち
絶対値がほとんど一緒の2つの数を演算したときに、有効桁数が急激に減ってしまうこと。
9999999999-9999999998=0000000001など。
④情報落ち
桁がすごい大きい数と、桁がすごい小さい数で演算をすると、桁がすごい小さい方の有効数字はまとめて切り捨てられてしまうこと。
パリティチェック
パリティビットというチェック用のビットを転送データに添付し、そのビットにおける1(ONビット)の数を数えて、データが正常に転送されたかどうかを確認する方法。
1の数が奇数だったら正常とするのが、奇数パリティ方式。
1の数が偶数だったら正常とするのが、偶数パリティ方式。
しかし、パリティビットが偶数個ひっくりかえると、反対の反対は賛成なのだ的に、正常な場合のビット数になってしまうので、誤りが検出できない。
パリティピーポー(前にも言った気がする)。
磁気ディスクの平均アクセス時間
以下の3つの時間の和で求められる。
①平均シーク時間
任意のトラックに読み取り用の磁気ヘッドをセットするのにかかる時間。
②平均サーチ時間
シークした後、指定されたトラックのデータ位置が磁気ヘッドに来るまでにかかる時間(音楽CDで任意の曲が聴きたい場合キュキュキュっとディスクが回転するときの時間)。
③データ転送時間
ディスクから目的のデータの読み取りを開始して、その読み取りが終了し CPUへの伝送が終わるまでの時間。
アクセス高速化
コンピュータがデータを処理するとき、内部では演算装置のCPUとメインメモリの間でデータが頻繁にやりとりされているが、CPUの方がメインメモリより仕事が早いので、CPUはメインメモリの仕事が終わるまで待たされる。これを解消する方法が以下である。
メモリインタリーブ
メインメモリをメモリバンクというそれぞれ独立した記憶領域に小分けして、これらのバンクにメモリアクセスを同時並行させる方法。
CPUがバンクAの場所Xにアクセスを開始したら、それと同時に別のバンクBの場所Yにアクセスを開始する。
キャッシュメモリ
メインメモリよりも高速で小容量のICメモリ。CPUとメインメモリの間にこれを置くことで、作業の仲立ちをさせる。
具体的には、CPUがデータをメインメモリから呼び出す際に、その前後にあるデータも一緒に読み込み、キャッシュメモリに移しておくと、次のデータを呼び出す際には、メインメモリではなく最初にキャッシュメモリを参照すれば、目的のデータが見つかりやすくなるといった仕組み。
これはCPUが次にアクセスする場所は、その直前にアクセスした場所の近くにありがち、というCPUあるあるを利用している。
ちなみに、CPUが必要とするデータがキャッシュメモリにない確率をNFP(ノットファウンド・プロバビリティー)と言う。
キャッシュメモリが複数実装されている場合は一次キャッシュ、二次キャッシュなどと呼ぶ。キャッシュメモリを介するデータの読み書きには2つの方式がある。
①ライトスルー方式
CPUがメモリにデータを書き込む際に、メインメモリとキャッシュメモリに同じデータを書き込む方式。メインメモリとキャッシュメモリのデータの整合が図られるため制御が容易だが、書き込み時間があまり変わらないため、高速化は望めない。
②ライトバック方式
CPUがメモリにデータを書き込む際に、高速なキャッシュメモリにのみデータを書き込む方式。書き込みは高速になるが、CPUの空き時間を利用してキャッシュメモリからメインメモリにデータの書き込みを行うため、制御がやや複雑となる。
プロセッサ(CPU)の高速化
CPUの制御装置は命令の取り出しと実行を繰り返してプログラムを処理しているが(現在のCPUだと1ギガヘルツで1秒間に10億回の計算をしている)、場合によっては前の命令が完全に終わる前に次の命令を開始することもできる(先回り制御)。
この制御は処理効率は上がるものの、動作は複雑になる。
パイプライン制御
制御装置の処理の手順はもう少し厳密に分けると
①命令の取り出し
②命令の解読
③オペランドアドレスの計算(オペランドとは演算対象となる値や変数)
④実アドレス交換
⑤オペランドデータの取り出し
⑥命令の実行
の6つになるが、例えば、ある命令が手順①を終了し②の段階に行くとき、次の命令の手順①の処理を並列処理するといったような手法がパイプライン制御である。
つまり、命令の数が6つ以上あって、最初の命令が手順⑥までいくと、①~⑥の全手順がところてん式に同時処理されることになる。
ディスパッチングアルゴリズム
複数ある実行可能プロセスから、どのプロセスにCPU時間を割くか(ディスパッチャ)を決定するアルゴリズム。
すべてのプロセスにはCPUに時間を充てるための優先度があり、この優先度によって緊急に処理するプロセスが認識される。
また、どのような順番でCPU時間の割り当てを行うのかを決定するアルゴリズムをスケジューラという。
①FIFO方式
ファースト・イン・ファースト・アウト。
プロセスの実行可能待ち行列に到着した先着順にCPU時間の割り当てを行う方式。
そのため、CPUの処理時間が長いプロセスが先に列に入ると、他のプロセスは長らく処理できない。
②ラウンドロビン方式
CPU時間を均等に割り付けて各タスクに分配する方式。
③プライオリティ方式
プロセスの優先度をあらかじめ決めておく方式。
④最短ジョブ方式
あらかじめジョブの実行時間がわかっている場合、処理時間の短いプロセスから優先的に割り当てる方式。