意外に喰らうオーバーフロー!
演算を行う際に演算内の最も大きなプリミティブなデータ型に統一して
演算をするはずだと思っていたら…
意外にそんな事は無かったりすらしい…。
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』での話だけど多分他のでも起きるのでは?
…多分…。
| 固定リンク
コメント