« 新鯖 | メイン | GeForce6600 »

■printf

投稿者 bois : 2004年10月12日 | [EDIT]

ゆうひさんが悩んでいるようなので・・

 コンピュータ上での小数値の扱いは、普通の数値と同じように2進数で扱うわけだから、
 10進数で0.5を二進数で0.1
 10進数で0.25を二進数で0.01
 みたいに考えて、次々に2で割りまくって細かい計算をしていると理解する。
 詳しい解説は、IEEE 浮動小数点 などのキーワードでぐぐってください

 そうすると、1.15ってのは二進数にとっては無限小数(循環小数)で、具体的には単精度の浮動小数点で「1.149991577748622946875」くらいなので、第1桁で四捨五入してしまうと1.1。
 1.25は、二進数にとってきっかり表現できる数値なので、誤差がなく表示される。
 そんな感じで、結果が変わって見えてしまうのだと思う。

 これを回避するのであれば、自前でなんとかしなければならないので、printfで細工。
 awkはよくわからないけれど、Cでやるならこうするかなぁ

  float num = 1.15f;
  printf("%d.%d", (int)num, (int)(num*10) % 10);

 ・1個目の%dは、整数部分。intにキャストして少数以下を切り捨て。
 ・2個目の%dは、小数1桁目。10倍したものをintにキャストして、10で割ったあまり(0〜9にするため)。
  awkだとここまで型を意識したコーディングはできないのかな・・


トラックバック

このエントリーのトラックバックURL:

http://www.boiscreative.com/blog/mt-tb.cgi/45


コメント

誤差というより、ただ四捨五入されてるだけっぽいけど…。

{ print int($1 * 10) / 10; }

こんな感じでできるのでは。

投稿者 m-akita : 2004年10月12日 20:40

あ゛、もう一度確認したら四捨五入じゃないっぽい(汗
という訳で上のコメントは、なかった事にしてください

投稿者 m-akita : 2004年10月12日 21:19

実際floatとかdoubleでプログラム組んでても、まさかこんなところに落とし穴があるなんて気づかないんで、いろいろ勉強になりますね。1.15を実は表現できていなかったという事実も、実はこの検証で初めて知りました(*´−`)・・・

投稿者 BOIS : 2004年10月15日 13:32




ログイン情報を記憶しますか?