👇のエピソードで統合開発環境Visual StudioとEAZY IDECでは数値計算結果が異なって表示されます。ですが根本的なコンピュータの数値計算の仕組みは全く同じなのです

☆実数値が1つでも計算式中に含まれている場合は計算式の計算結果が整数値になっても%d出力変換指定子でなく%f出力換指定子を使用してください



☆実数値が1つでも計算式中に含まれている場合は計算式の計算結果が整数値になっても%d出力変換指定子でなく%f出力換指定子を使用してください☆




そのころ、ソーラーが眠るのを見届けたニーモは


好き放題やっていた。


やっぱり妖精さんはみんないたずら好きなんだね。


                 solarplexuss


ソーラーの前では内側におさえていた光を怒涛のごとく


開放する。


あたりがニーモの光圧で何も見えないほど真っ白に染まる。


ニーモ 「やっぱり、こうでなくっちゃ。」


あたりが光で埋め尽くされ満足げに


微笑むニーモ。


寝ているソーラーをみると


ニーモ 「あっいい場所、みっけ。」


めざとくマイスペースをみつけると


しゅんとニーモは瞬間移動しソーラーの額の上にちょこんとに腰掛ける。


ニーモ 「ここいいわ。楽チン、楽チン^^♪♪♪~ 」


思い切りからだをのばし、


ソーラーの額に手をついて脚をぱたぱたさせてみる。


たっくさん上機嫌で歌を歌った後、


そのままソーラーの額に寝っころがりながら


ソーラーの額をぴちぴちたたきだす。


ニーモ 「おっもしろ~い。」


元気な妖精からは絶え間なく光があふれだし


ソーラーにもその光は直接ふりそそいでいた。




ソーラー「つまり、今のプログラムでは


int a;

a=1.05;


このように


実数値1.05を整数型であるint型の変数aに格納するから


小数点以下の数値0.05は


切り捨てられ


変数aには1しか格納されないんだよね。 


だから


今の目的のプログラムの実行結果


あなたの預金額はただいま10500円です。


が表示されないプログラム

👇

#include <stdio.h>


int main(void)

{

int a;

a=1.05;


printf("あなたの預金額はただいま%d円です。\n",10000*a);

return 0;

}


プログラムの実行結果(EAZY IDECの場合)

プログラムの実行結果(Visual Studioの場合)


あなたの預金額はただいま10000円です。


👆


を変更して


あなたの預金額はただいま10500円です。


と表示させるには


int a;

a=1.05;

によって


変数aに格納される数値が1.05から1に変更されるのを


ふせぐため



次のプログラムのように


#include <stdio.h>


int main(void)

{

float a;/*ここがかわりました。*/

a=1.05;


printf("あなたの預金額はただいま%d円です。\n",10000*a);

return 0;

}


と記述されなくちゃいけないんだね。」


(ほんとかな~~?(*´▽`*))


ソーラー「それでは😊


コンパイルっ」




プログラムの実行結果(EAZY IDECの場合)


あなたの預金額はただいま-262144000円です。



プログラムの実行結果(Visual Studio2018の場合)


C4305 '=': 'double' から 'float' へ切り詰めます。 Project6 c:\users\solarplexuss\source\repos\project6\project6\source.cpp 6

警告 C4477 'printf' : 書式文字列 '%d' には、型 'int' の引数が必要ですが、可変個引数 1 は型 'double' です Project6 c:\users\solarplexuss\source\repos\project6\project6\source.cpp 8


と表示されますが


プログラムの実行結果


あなたの預金額はただいま0円です。



コマンドプロンプト画面に表示されます






プログラムの実行結果(Visual Studio2019の場合)


重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態

警告 C6273 整数でない値が _Param_(2) として渡されました。'printf' への呼び出しには整数が必要です。実際の型: 'float': ポインター値を渡す場合は、%p を使用してください。 Project2 C:\Users\solar\source\repos\Project2\Project2\program1.cpp 8

警告 C26451 演算のオーバーフロー: 4 バイトの値に演算子 '*' を使用し、結果を 8 バイトの値にキャストしています。オーバーフローを避けるため、演算子 '*' を呼び出す前に値を幅の広い型にキャストしてください (io.2)。 Project2 C:\Users\solar\source\repos\Project2\Project2\program1.cpp 8

警告 C4305 '=': 'double' から 'float' へ切り詰めます。 Project2 C:\Users\solar\source\repos\Project2\Project2\program1.cpp 6

警告 C4477 'printf' : 書式文字列 '%d' には、型 'int' の引数が必要ですが、可変個引数 1 は型 'double' です Project2 C:\Users\solar\source\repos\Project2\Project2\program1.cpp 8



と表示されますが


プログラムの実行結果


あなたの預金額はただいま0円です。



コマンドプロンプト画面に表示されます



ソーラー「ははは


intをfloatに変えてプログラムを記述すると


うまくいくは・・・


ず・・・???😝


プログラムの実行結果(EAZY IDECの場合)


あなたの預金額はただいま-262144000円です。

!!!


な、なんで・・・?


どしぇえええええええ~~~


ついでに


プログラムの実行結果(Visual Studioの場合)


あなたの預金額はただいま0円です。


だってぇ~?」


🍋🍋🍋


なぜ  このようなことが起きるかというと


printf("あなたの預金額はただいま%d円です。\n",10000*a);


に秘密があります。


今のプログラムの場合


a=1.05が10000*aに代入されるので


10000*a=10500となり


整数値を出力するのに用いられる%d出力変換指定子でよいのではないかとおもわれるとおもいます。


わたしも そうおもいました。


ですが タイトル名にもありますように


🍅実数値が1つでも計算式中に含まれている場合は


計算結果が整数値になっても


%d出力変換指定子でなく%f出力変換指定子を使用する🍅


という仕様になっています


なぜ このようなことが起きるのかというと


それは コンピュータの数値計算方法の仕組みにあります。


コンピュータは


整数型なら整数型


実数の型なら実数の型の形式でメモリに格納されている数値同士でしか計算を行うことはできません。


同じ整数の型の形式でメモリに格納されている数値同士の計算


5×5

5+5なら


そのまま計算を実行できますが


異なる型の形式でメモリに格納されている数値同士の計算


5×8.28888や

1.23456+10などは


そのままでは計算できないのです


詳しく説明すると



printf("あなたの預金額はただいま%d円です。\n",10000*a);


において


10000は整数なので整数の型(int)の形式でメモリに格納されます。


(つまり

コンピュータのメモリ内では

10000はint型の形式で格納されています。

このことは

ビット・バイトの説明のときに詳しく解説されます)


そして


10000*aの変数aがfloat型の変数の場合 


変数a(に格納されている数値データ)は実数の型の形式でメモリに格納されているので


このままでは


整数値の型の形式でメモリに格納されている10000×実数の型の形式でメモリに格納されている変数a(に格納されている数値データ)


となってしまい計算できません。


そこでコンピュータは


整数値10000を実数10000.000000・・・に変換


そして 実数の型(double)の形式でメモリに格納しなおします


そのように整数値10000を実数に変換して


同じ実数型同士である


実数の型の形式でメモリに格納された実数値×実数の型の形式でメモリに格納された実数値の計算にもっていきます。


つまり


実数の型の形式でメモリに格納されている10000×実数の型の形式でメモリに格納されている変数a(に格納されている数値データ)


に変換して計算をおこなうというわけです。


このように

       🍓実数の型の形式でメモリに格納されている実数値と🍓

  

     🍓整数の型の形式でメモリに格納されている整数値の計算では🍓


       🍎整数の型の形式でメモリに格納されている整数値は🍎


    🍎実数の型の形式でメモリに格納し直されることになります つまり実数値に変換されます。🍎


そのようにして


実数の型の形式でメモリに格納されている実数値同士の計算に変換されてから


数値計算がをおこなわれるというわけです。


つまり


計算式中に1つでも実数があれば


その計算式の中の他の整数値はすべて実数値に変換されます。


そして


その計算結果も


実数の型(double)の形式でメモリに格納されます。


よって10000*aは実数となるわけです


ですので


              10000*a=実数(🌞実数というところがポイントです)



をprintf出力表示するには%d出力変換指定子でなく


%f出力変換指定子が必要になってくるというわけです。


よって


今のプログラム

👇

#include <stdio.h>


int main(void)

{

float a;

a=1.05;


printf("あなたの預金額はただいま%d円です。\n",10000*a);

return 0;

}


プログラムの実行結果(EAZY IDECの場合)

あなたの預金額はただいま-262144000円です。


プログラムの実行結果(Visual Studioの場合)

あなたの預金額はただいま0円です。




👆




は整数値を出力する%d出力変換指定子を


実数値を出力する%f出力変換指定子にかえて


👇

#include <stdio.h>


int main(void)

{

float a;

a=1.05;


printf("あなたの預金額はただいま%f円です。\n",10000*a);

/*🌞%dが%fにかわりました。🌞*/


return 0;

}


と記述するのがただしいというわけです😊


そうすると


プログラムの実行結果(EAZY IDECの場合)


あなたの預金額はただいま10499.999523円です。


がprintf出力表示されます。


プログラムの実行結果(Visual Studioの場合)


C4305 '=': 'double' から 'float' へ切り詰めます。 Project6 c:\users\solarplexuss\source\repos\project6\project6\source.cpp 6

が表示されますが


プログラムを実行すると


あなたの預金額は10500.000000円です。


がprintf出力表示されます。


めでたしめでたし😊


🍋🍋🍋

って めでたくないって?


ソーラー「a=1.05が10000*aに代入されるのであれば


プログラムの実行結果(EAZY IDECの場合)は


10000*a=10500.000000となるはず 


それが10499.999523・・・


になるって・・・???


統合開発環境Visual Studioでは


正しく


あなたの預金額は10500.000000円です。


が表示されてるのに・・・?」



🌞  🌞  🌞

ここで


統合開発環境EAZY IDECと


統合開発環境Visual Studioの違いが


はっきりでてきましたね。


なぜ統合開発環境EAZY IDECでは


プログラムの実行結果


あなたの預金額は10499.999523円です。


がprintf出力表示され



統合開発環境Visual Studioでは


プログラムの実行結果(Visual Studioの場合)


あなたの預金額は10500.000000円です。


と正しくprintf出力表示されるのか?


統合開発環境Visual Studioは最新の統合開発環境なので


正確に


あなたの預金額は10500.000000円です。

が表示されていますが



古いタイプの統合開発環境EAZY IDECでは


あなたの預金額は10499.999523円です。


となぜか微妙な数値が表示されています。


おもしろいですね。


実は


古いタイプの統合開発環境EAZY IDECは


正しく計算結果を表示しています。



この違いがなぜでてくるのかは


コンピュータの数値計算の仕組みを理解すれば


わかるようになります。





  • Twitterで共有
  • Facebookで共有
  • はてなブックマークでブックマーク

作者を応援しよう!

ハートをクリックで、簡単に応援の気持ちを伝えられます。(ログインが必要です)

応援したユーザー

応援すると応援コメントも書けます

新規登録で充実の読書を

マイページ
読書の状況から作品を自動で分類して簡単に管理できる
小説の未読話数がひと目でわかり前回の続きから読める
フォローしたユーザーの活動を追える
通知
小説の更新や作者の新作の情報を受け取れる
閲覧履歴
以前読んだ小説が一覧で見つけやすい
新規ユーザー登録無料

アカウントをお持ちの方はログイン

カクヨムで可能な読書体験をくわしく知る