質問: 具体的には、 ``` (int)(1.16*25) ``` の値は、28 ``` (double)(1.16*25) ``` の値は、29 となってしまいます。 理由と解決策を教えてほしいです。 開発環境は、mac os x high sierra、コンパイラはg++です。
回答: こんにちは。 浮動小数点型の多くの内部表現は2進数です。その小数点以下の値を10進数で表現すると、0.5, 0.25, 0.125, ...を組み合わせて足したものです。 ですので、実は0.16をピッタリ2進数で表現することができません。 1.16 = 1.0 + 0.125 + 0.3125 + 0.0078125 + ... 有限桁の2進数で表現するため、最後は切り捨てなどで丸められています。 ですので、1.16の内部表現は、1.16よりほんの僅か小さな値になっているようです。 それを25倍すると、29よりほんの僅か小さな値になります。それを整数へ単純に変換するのでまるっと小数点以下が切り捨てられて28になります。 整数へ変換ぜずにdoubleで受けても同じく29よりほんの僅か小さな値(例えば、28.9999999999)になりますが、doubleは切り捨てずに記録できます。そしてそれを表示する際、小数点以下の数値は数桁程度で丸められます。その際四捨五入されますので、9が四捨五入されて切り上げられるため、29になります。 対策はint型へ変換する際に四捨五入する(例えばround)のが手っ取り早いです。 (なお、負の数の四捨五入には要注意です。四捨を0に近い方へ切り上げる、もしくは、0から遠い方へ切り捨てる2種類のやり方があります。)