#pragma twice

KAB-studio > プログラミング > #pragma twice > 226 Version 12.03 パソコンは計算機

#pragma twice 226 Version 12.03 パソコンは計算機

前のページへ 表紙・目次へ 次のページへ

 Version 12.03
パソコンは計算機

今回から数回、かなーり難しい〈実数〉っていうものについて見ていきま

じっすー?
簡単に言うと小数点を含む数値のこと。 int は整数値だから小数点は含
まないでしょ
つまり小数点を使うときには int じゃダメだから、なんか使わなきゃい
けないってことね
そういうこと。で、まずは小数点を表示する方法から。 TRACE() とかの 
printf() 系は、 %f で実数を出力できます

void OutputFloatingDigit()
{
    TRACE( "%f\n", 1.0 );
    // 1.000000
}

お、簡単に出た
ところが、たったこれだけのことに、とっても複雑な問題がいっぱい存在
します
げげ
まずはこれ

void OutputFloatingDigit_Bad()
{
    TRACE( "%f\n", 1 );
    // 0.000000
}

……え、マジ……?
まじです
だって、 1 と 1.0 って同じでしょ!?
コンピューターの世界では違うって事

 1 を16進数で表すと?
んー、 0x01 みたいな?
そうだね。で、実数の 1.0 を16進数で表すと、ぜんっぜん違うものに
なります
なんで?
小数点も含めなきゃいけないから
あー……って、整数のとこは互換とかそーゆーのないの?
ありません。つまり、整数と実数とでは、ビット単位での表現方法が全く
違うです
なにそれー
 TRACE() は %f を見て〈実数がある〉ってみなしたから
実数のビットを見る感覚で整数値を見ちゃった、と
そういうこと
……ねー、これからその数回ってゆーの、休んでいい?
意味ないし
う”……
今言った〈実数のビットでの表現方法〉は後にとっておいて、次に、小数
点の話
小数点?
 %f の % と f の間に、 .数字ってすると、小数点の表示桁数を変えられ
るんです。たとえば20桁表示するんなら

void OutputFloatingDigit20()
{
    TRACE( "%.20f\n", 1.0 );
    // 1.00000000000000000000
}

ってなるし、1桁しか表示しないなら

void OutputFloatingDigit1()
{
    TRACE( "%.1f\n", 1.0 );
    // 1.0
}

ってなります
 . の後に桁数ね
これはちゃんと四捨五入してくれます

void OutputFloatingDigitRound()
{
    TRACE( "%.1f\n", 0.04 );
    TRACE( "%.1f\n", 0.05 );
    // 0.0
    // 0.1
}

おー、ちょっと便利
で、なんでこういう機能が付いているかというと、そもそも実数には誤差
がある、っていうのがあるんです
げ、 Version 12.01 ( No.224 ) でやったのだ
そう

void Double01()
{
    TRACE( "%.20f\n", 0.1 );
    // 0.10000000000000001000
}

やっぱ変なとこに 1 が入ってる……
さっき言ったように、実数のビットでの表し方は整数と違ってて、その表
し方が原因で、こういう誤差が普通に起きるんです
それってこまんなくない?
困るよ。特にお金の計算とか
お金?
こういう誤差が積もり積もるとすごい額になっちゃうから
そういえば……
だから、そういうときにはちょっと違う方法で実数の計算をするんだけ
ど、それはまた今度ってことで。あと、特に困らない場合もあるし
困らない場合?
物理計算とか
ぶつり……けいさん?
実験とかで、物が落ちたり跳ねたりを計測して、その計算をするとかそう
いう計算の場合
なんでそんときには困んないの? それだって困るでしょ
元々、そういう計算には誤差がつきものだから。定規で、本当に正確に1
ミリを計るってできないでしょ
ん……確かに、定規の目盛りもあるから、本当に正確にって無理だね
だから、科学的な計算では常に誤差が生じるから、その辺を踏まえて計算
するのが普通
だから double の誤差も問題ない、と
ま、計算するときには考慮する必要があるけど、それは普通の誤差と同じ
ようにってことだから
その気を付けることって?
今回はパス。計算方法自体はプログラムに関係なく普通の計算で使うもの
だから、そういうのを勉強したときに教わると思うよ
そういうのを勉強するとき?
大学の実験とか
大学、ねぇ……
そういう特別な状況でもない限り、こういう計算はしないから。ただ重要
なのは、コンピューターの最初の目的は、こういう計算だったってこと
こういう、って、科学的な計算ってこと?
そう。コンピューター自体【計算機】って呼ばれてたし。だから、そうい
う計算まわりの機能は初めから備わってる、ってところかな。たとえば

void IntToDouble()
{
    int i = 100;
    double d = i;
    TRACE( "%f\n", d );
    // 100.000000
}

 int に入れて、それを double に入れてる
 double は実数を入れる変数。つまり、 int から double へは自動的に
変換ができるってこと
それってすごいの?
だって、整数と実数はビット的には全然違うんだから
そっか、ただ入れるんじゃなくて、その変換をして入れてるってことなん

そういう機能は初めから備わってるってこと。文字列との変換はランタイ
ムが必要なのに
その辺が、計算機って理由なのね
もうひとつ計算機らしいところをあげると、 E 表記っていうのもありま

いー?

void OutputDoubleE()
{
    TRACE( "%E\n", 0.1 );
    // 1.000000E-001
}

むむむ? なんか変な書き方だ
 E-001 っていうのは、 10 の -1 乗って意味。 E が〈 10 の何乗か〉
って意味で、 -001 が -1 
 10 の -1 乗……
は10分の1だから 0.1 。これを、 E の左側に掛けたのが正しい値
 1.0 に 0.1 だから、 0.1 ……なんかめんどい
これは科学的な書き方だから、なじみがないと思うけど、実は実数のビッ
トでの表現方法を考える時に重要なことだから、ちょっと憶えておいて
一応憶えとく
最後にもうひとつ、これは科学的なのとは関係ないもの
ほっ……
整数値の割り算をするときに気を付けなきゃいけないことがあります。そ
れは、整数値どうしの割り算は整数値になっちゃうってこと


void OutputIntDivide_Bad()
{
    double d = 1 / 2;
    TRACE( "%f\n", d );
    // 0.000000
}

げ、 0 だ
 1 も 2 も整数値だから、 1 / 2 の答は 0.5 なんだけどこれが整数値に
変換されちゃうから 0 になっちゃうんです
げ、しかも切り捨てだし
キャストは基本的に切り捨てだから。これを避ける場合には、どっちかを
実数にします

void OutputIntDivide_Good()
{
    double d = 1 / 2.0;
    TRACE( "%f\n", d );
    // 0.500000
}

お、 2.0 にしただけでできた
 同じく 1.0 でもいいから。というわけで、実数はむつかしいことがいっ
ぱいあります
で、まだまだ出てくると
そういうこと

/*
    Preview Next Story!
*/
なんっか、ホントにかなりややこしいんだけど……
僕もそう思う
水希ちゃんも?
普通のプログラムって、実数ってあまり使わないから
たいがい整数で間に合っちゃうんだ
僕自身あまり慣れてないから
プロでも難しいわけねー
というわけで次回
< Version 12.04 浮動小数点型 >
につづく!
でもひととおりは理解してもらうからね
意味あるの?
こういう勉強は、必ずあとで役に立つから
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。