float型に潜む罠

ステージ作るのにしばらく時間かかりそうなので今回はTips的に

今回は小数点の表現の代表であるfloat型について見ていきたいと思います。

float型とは

float型とは難しく言うと浮動小数点型、小数点をプログラム上で表現するための基本型です。

Unityでもよく使用する型ですね。

数字の表現範囲は

範囲
int-2,147,483,648 ~ 2,147,483,647
float-3.402823e38 ~ 3.402823e38

圧倒的違いですね

これであれば一見int以上に表現できる数が多いためfloatが良さそうに見えますが

これはです。

絶対に使い分けなければなりません。

罠その1:表現できる桁数

罠のその一つに表現できる桁数に限界があるということです。

Microsoftのドキュメントによると、有効桁数が6~7桁とのこと

例えばこの 123,456,7890 の数字を表現したい場合

int型とfloat型の表現方法は普通はこうなります。

int型

123,456,789

普通に整数なのでそのまま表示されます。

float型

1.23456789×109

※厳密には違いますが人間に可能な限りわかりやすく表現すると

×10n表現になります。

しかし、

有効桁数が6~7桁 なので実際はこうなります

1.23456×109

789の下3桁が抜けましたね

この通り桁数の限界で数字が抜けてしまうこともあるので注意が必要です。

罠その2:表現可能な数字に限界がある

もう一つは一見不可思議で理不尽ですが、表現できる数字に限界がある点です。

例えば以下のような計算

1 + 1 = 2

普通に計算すれば考える必要もなく2となりますが、ところがfloat型で計算すると

1 + 1 = 0.9999999999…

もしくは

1 + 1 = 1.000000000…1

なにか様子がおかしいですね。

原因様々な記事で書かれていますが簡単に言うとメモリ上の方の表現方法の問題で

表現できない数字は近似値でだいたい近い数字に丸め込まれるようになります。

しかもこの値、計算するCPUや端末、アプリ仕様で全く違う結果になるということです。

クロスプラットホームで通信対戦を作ろうと思うのなら、

この仕様はかなり致命的で

FPSなど反応や位置取りが重要視されるゲームではゲームが崩壊しかねないので

絶対に対策が必要となります。

対策方法

この誤差に対する対策方法は様々で

  • 整数型で対応する
  • 独自の小数型を実装
  • 有効な桁数を予め決めておく
  • floatの数字をそもそも信用しない
  • そういうものだと改めて使わせてもらう
  • 諦める

といろいろあります。いくつか今すぐできそうなものがありますね。

特にそういうものだと知っておくことは非常に重要ですね。

知っていることでこんな処理は絶対書いてはいけないとはわかるようになります。

float x = 1.0f;

x += 1,0f;

if(x == 2.of)
{
    // なにかの処理
}

記事を見たあとではこの if文でなにかの処理が実行されることは極めて低いことがわかりますね。

どうしてもこの処理を通したい場合はある程度の誤差を許容し以下のようにする必要がありますね。



float x = 1.0f;

x += 1,0f;

if(1.99f < x && x < 2.01f)
{
    // なにかの処理
}

まとめ

float型は非常に重要で、座標系の計算や数学としては必須ではありますが

値を過信してはいけないことがまじまじと伝わって来ましたね。

値を使用する場合は、値は正確ではないことを前提に作ってきましょう。


コメントを残す

メールアドレスが公開されることはありません。

ABOUT US

vuniformity誰でもない人
トレンドの行く末を見守っている
仮名を名乗るエンジニア

ゲーム開発は仕事であり趣味である
プログラムだけでなく多種多様なスキルを数多く持つ

ゲーム開発は
ソーシャルゲームを開発運用の経験アリ
ゲーム以外にも経験アリ
Webサービス保守開発等に携わる

ゲームプレイの主な戦場は
FGO
FEH
MTGA
マビノギ
ここでは主にunityroomで公開しているゲーム作り直しの軌跡を綴っていきます