« 201系の実物大オブジェ? | トップページ | 生、管直人! »

2009年7月30日 (木)

意外に喰らうオーバーフロー!

演算を行う際に演算内の最も大きなプリミティブなデータ型に統一して
演算をするはずだと思っていたら…

意外にそんな事は無かったりすらしい…。

Cでは暗黙の型変換で『算術変換』てのがある。

例えば、以下の例だと…
    double    a    = 1;
    int        b    = 2;
    a    = b;
    b    = a;
『b=a』では、『warning C4244: '=' : 'double' から 'int' に変換しました。』って警告が出る。

どうやらこれで勘違いをしていたみたいだ…。

右辺の演算結果が『double』なのなら、演算は『double』で行っているに違いない!

てな感じで…。

実際に試してみる…。

#include<stdio.h>
#include<math.h>
void main( void )
{
    int    SourceRate    = 44100 * 2 * 2;
    int    SourceCount    = 400000;
    int    ObjectRate    = 11025 * 2 * 2;
    printf( "1:%6d ( <= 100000 )\n", ( int )
( ObjectRate * SourceCount / SourceRate + 0.99 ) );
    printf( "2:%6d ( <= 100000 )\n", ( int )
( ( double )ObjectRate * SourceCount / SourceRate + 0.99 ) );
    printf( "3:%6d ( <= 100000 )\n", ( int )
( ObjectRate * SourceCount / SourceRate * 1.0 + 0.99 ) );
}

結果は、以下の通り。

1:  2608 ( <= 100000 )
2:100000 ( <= 100000 )
3:  2608 ( <= 100000 )

2以外は、オーバーフローが発生して正しい値にならない…。

算術中は、算術優先順に計算を処理して行き
異なる型の計算でキャストが必要になったら
その時点でキャストを行うようだ…。

ただし、大きな型から小さな型への変更が無いため最終的には、
最も大きな型での結果となる訳らしい。

基本的には『int』で間に合うし、そうでない場合には『float』で統一していたりする。

従ってこう言うのは、あまり喰らわなかった気がする…。

…忘れてしまっただけかもしれないが…。

まあ、『double』の切り上げを『+0.99』で無く『ceil』を使えば良かったのかな…?

キャストも出来て一挙両得かと思ったんだけどね…。

兎にも角にも最初に演算する値を最大の型にしろって事らしい…。

たまに全てにキャストを付けているのを見かけたりする。

…微妙?

まあ、今時のCPUは早いから全部『double』ってのも手かもしれない…。

勿論、自分はしないと思うけど…。(^_^;)

PS.

『Microsoft Visual Studio 6.0』での話だけど多分他のでも起きるのでは?

…多分…。

|

« 201系の実物大オブジェ? | トップページ | 生、管直人! »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: 意外に喰らうオーバーフロー!:

« 201系の実物大オブジェ? | トップページ | 生、管直人! »