![]() パステル オービット |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
---|
ゲームプログラマが語る。「浮動小数点」と商業レベルで上手に付き合う方法
|
![]() やや間の開いた更新であるにも関わらず次週のサザエさんは的な勢いで冒頭からボケ倒してみたいところでありましたが最近周囲が繰り出す「不安の範囲攻撃」に苛まれている内にやる気もネタもなくなり、結局何を書こうと思ったんだったのでありましょう。 夢の中でヤドカリと会話する様な人はどうかと思いますが、いっこうに会話の内容を思い出す事が出来ず、不安すぎて昼も眠れないTeamDyquemで御座います。皆様、こんにちは。 次回のエントリー用「ガッツリ宇宙ネタ」草稿も併せて書いておりましたので、何となく気分が宇宙的な感じでありますが、ペテルギウスの超新星爆発による人類壊滅も目前に迫った本惑星であります事ですしね。 気を取り直して、ゲーム製作初心者さん向けエントリーを一つ。 ![]() 整数と、浮動小数点 題材として、何か大きな数値が必要ですね。 光は1秒間に約30万キロメートル進むわけですが、これを例にとってみましょう。 もう少し正確に言えば29万9792.458キロメートル。キロではなくメートルで表現する為に全部数字を並べれば「299792458メートル」という大きな数値です。 32ビット符号無し整数の最大値が「0xffffffff==4294967295」ですから、この値を32ビット符号無し整数として扱う事は可能です。しかし、32ビットを単純に整数として扱う場合には「299792458.0+0.00001」の様な少数部の含まれる計算は行えませんし、そもそも「299792458+5000000000」の様な更に大きすぎる値を伴う計算も行えません。整数として数を表現する為の「幅」が32ビット幅を超えて広がってしまう事が原因で、これはビット精度不足と呼称されています。 ![]() 整数型の限界を超える、浮動小数点型 こうした点を解消する為のアプローチとしてfloat型(double型)という型が考案され、IEE754という標準規格の元、世界的に広く運用されているわけでありますが、その仕組みについて本当に把握している方はあまり多くない様に思います。 ゲームプログラマにとり、float等に代表されるこれらの型との縁は切っても切る事は出来ませんし、完全な見方につけるべき概念でありますからね。 一つ、掘り下げてみたいと思います。 float型はご存じの通り32ビットの型でありますが、上記の符号無し32ビット整数では解決出来ない小数部を含む数値の扱いや、非常に大きな数値の扱い等の問題を制限付きで解決します。同じビット長であるにも関わらずこれが解決出来る仕組みは、そう難しいものでは在りません。 これら「浮動小数点」と呼ばれる型は、floatならばその32ビットの中を3つのフィールドに分けて管理しています。内訳は符号1ビット + 指数8ビット + 仮数23ビットとなっており、IEEE754フォーマットとして定められています。
という並びですね。 浮動小数点の仕組みを簡単に言えば、「仮数部=種となる数字」「指数部=種を何乗にするか」「符号=プラスかマイナスか」という物であります。 キーとなるのは指数部の「何乗にするか」という部分であり、実際には「10の何乗に」するかという指数でありますが、例えば10の8乗にする為に「8」という意味の数値を指数部にセットしておけば、種が10の8乗された非常に大きな値を取り扱う事も可能となりますし、逆に「10のマイナス8乗」という意味の数値を格納する事により、「0.0000…1」の様な非常に小さな数値を表現する事も又出来るのです。 冒頭の「光の速度=299792458メートル」を実際に float型にてビット化するならば、光速299792458の仮数は2.99792458、指数は10の8乗、つまり8でありますから上記の様に表現する事が可能となるわけであります。 この時、デバッガ等でその値を確認してみると、299792448.0f という意味を表す実際の32ビット値は [0x4d8ef3c2] となっている事を確認出来るでしょう。 IEEE754にて定められたフォーマット、 実際の数値 = 符号 × 2(指数-127) × (1+仮数) へ当てはめてみれば、まさに上記の値となる事が判りますが、この辺りの詳細は種々ネット情報等へ譲り先へ進みます。 ![]() 浮動小数点型が犠牲にしているもの 浮動小数点型は、非常に大きな値でも、非常に小さな値でも、指数を活用し表現する事の出来る優れた型であります。指数の幅はfloatならば8ビットもありますので、相当に大きな値でも、また、相当に小さな値でも表現する事が可能です。 例えば、上記の光速 「299792448.0」。 例えば、もの凄く小さな値「0.000001」。 どちらも、指数部8ビットを大きく活用しfloatで表現する事の出来る値である事は確かです。 しかし。 上記二つの値を合算する事は出来ません。 「299792448.0 + 0.000001」を行う場合、大きな値から小さな値までの「指数の幅」が8ビットを超えてしまい、値の小さな部分に対しての「丸め」が発生。 結果、この演算は無かった事になるのです。 「丸め」とは、その表現における限界を超えた部分に対して、最小の影響にて施される回避策です。制限を超えたビットに関する演算結果を「捨てる」という挙動であり、数学的には「近似」と表現され得ますが、演算結果の一部が捨てられている事実に変わりはなく、所謂「計算誤差」という形となって表面化する事も少なくありません。 この様に、浮動小数点には限界があり、その犠牲として計算誤差が発生する恐れが存在します。 この辺りの詳細は、「イプシロン」等で調べてみても面白いかもしれません。 ![]() ゲームに及ぼす影響 商業ゲームを製作するに辺り、こうした特性を把握しておく事は大変重要であります。 例えば以下の事例。 前回のエントリー、 ゲームプログラマが語る書評:「ゲームエンジン・アーキテクチャ」を読んでみた にて紹介させて頂いた書籍より、例として拝借致します。 昨今のゲームにて目にする事もあるかと思いますが、「プレイ時間」という情報について例にとってみましょう。(モンハン等では、これが300時間等に達している方も少なくないでしょう。) 単純に秒の蓄積を表す器として、float mSumOfPlayTime; 等の様な変数にしてしまうと、この段階でアウトです。 この変数へ、毎秒30フレームのゲームがフレーム毎に経過時間を加算していくとしましょう。 mSumOfPlayTime += 1.0f / 30.0f; 1の30分の1とは、0.033という小さな値です。これが mSumOfPlayTime に蓄積される値はどんどんと大きくなり、いずれは「光の速度」の様に非常に大きな数値へと育って行くでしょう。 上記にて「299792448.0 + 0.000001」が丸めにより計算できなくなる例を出した様に、mSumOfPlayTime にも、指数により運命を定められた限界を突破するXデイが着々と迫ります。 Xデイを迎えるとそれ以上プレイ時間は加算されず、どんなにプレイしてもそれ以上の時間が表示されないという重大なバグへと育ちます。 さて、そのXデイとは? 延々と1/30秒を加算し続けてく場合、それは約12.9日後にやってきます。 ハマリにハマれる素晴らしいゲームにおいて、プレイ時間の合計はユーザーの勲章でもありましょう。300時間超えでプレイしてもらえるという素晴らしいゲームでありながら、そのまま実装していたならば、「プレイ時間表示は309時間でカンスト」というなんともお粗末なバグにより、一気にユーザーを興ざめさせる事でしょう。 ![]() 本質を知り、上手に付き合う こうした事態を十分に想定し、精度を意識した実装を心がける事が大切です。 経過時間を計るならば、それに適した構造体型を用意するべきでありましょう。ミリ秒、秒、分等を別々のメンバとして含み、加算メソッド等を用意すれば事足りるのです。そうした組み込み型も存在しています。 体長が50メートルもある様な巨大なボスの持つ絶対座標矩形情報に1ミリを加算しても意味が無く、「このボスの座標に1ミリを加算していき、丁度1メートルだけ動いたら次の処理へ」。 こういう動作があった場合、このボスはこの段階で停止する事でしょう。 精度不足の値が加算される事そのものではなく、「その加算には単に意味が無いだけで、動作に影響は及ぼさない」という実装を常に意識する事が重要でありましょう。 丸め誤差も精度不足も、それと判って付き合っていけば、これほどまでに役立つアトミック型はありません。「小数部が使える」という表面的な部分だけに捕らわれず、その本質を理解した上で、上手に付き合っていきましょう。 「アトミック型」につきましては、以前のエントリー iPhoneアプリ作者が語る。マルチプラットフォーム化その2・アトミック型定義のススメ 上記も併せて参照頂けましたら幸いです。 さて、週の真ん中水曜日。 今週ももう少し頑張って参りましょう。 ちなみに、次回は恐らく本当に「ガッツリ宇宙ネタ」の予定で御座います。 ゲームエンジン・アーキテクチャ posted with amazlet at 12.01.06 ジェイソン・グレゴリー ソフトバンククリエイティブ 売り上げランキング: 58316
![]() シリーズ記事まとめ ■Aニュース、ガジェット通信 寄稿記事 「『連載.jp』寄稿「ゲームプログラマが語る「プロ棋士に勝ったAIは、タクシー基本無料化をもたらす?」」」 「『Aニュース/ガジェット通信』寄稿「ゲームプログラマが語る ”買わない理由”がもたらす充足感と、開発者達の心理」」」 「『Aニュース/ガジェット通信』寄稿「ゲームプログラマが語る アップデート版に潜む開発者モラルハザード」」 「『Aニュース/ガジェット通信』寄稿「ゲームプログラマが語る ソフトやアプリと携帯ゲーム課金における経済行動学」」 「『Aニュース/ガジェット通信』寄稿「ゲームプログラマが語る。新しいゲーム機が定期的に生まれる理由」」 「『Aニュース/ガジェット通信』寄稿「ゲームプログラマが語る 楽しさの仕組み ゲームメカニクス」」 「『Aニュース/ガジェット通信』寄稿「ゲームプログラマが語る 3Dテレビとゲームの微妙な関係 その打開策」」 「『Aニュース/ガジェット通信』寄稿「ゲームプログラマが語る 無料アプリのビジネスモデルと舞台裏」」 「『Aニュース/ガジェット通信』寄稿「新発表ラッシュに見るクラウド大航海時代の幕開け」」 ■ゲーム制作初心者さん向け系 ゲームプログラマが語る。なんちゃってリードプログラマにはなるな!ゲーム造りで放棄してはいけない大切な事 ゲームプログラマが語る。今さら聞けないフレームレートに纏わる話。秒間60?16ミリ? ゲームプログラマが語る。「浮動小数点」と商業レベルで上手に付き合う方法 「ゲームプログラマが語る。ゲーム制作初心者の方へ小ネタ「クォータービュー入門」」 「ゲームプログラマが語る。「正しい乱数」が彩る確率世界とエンターテイメント」 「iPhoneアプリ、ゲーム制作初心者の方へ小ネタ「線分と円の交差」」 「iPhoneアプリ作者より、ゲーム制作初心者の方へ小ネタ「2Dベクトル」」 「iPhoneアプリ作者より、ゲーム制作初心者の方へ小ネタを一つ」 ■「プロのゲームプログラマとして、ゲーム製作に関する書評を」シリーズ ゲームプログラマが語る書評:「MMORPGゲームサーバープログラミング」を読んでみた ゲームプログラマが語る書評:「ゲームプログラマになる前に覚えておきたい技術」を読んでみた ゲームプログラマが語る書評:「ゲームエンジン・アーキテクチャ」を読んでみた ■個人でも出来る、マルチプラットフォーム開発関連 「ゲームプログラマが語る。iOSゲームをWinマルチプラットフォーム開発・その4」 「ゲームプログラマが語る。iOSゲームをWinマルチプラットフォーム開発・その3」 「iPhoneアプリ作者が語る。マルチプラットフォーム化その2・アトミック型定義のススメ」 「ゲームプログラマが語る。iOSゲームをWinマルチプラットフォーム開発・その1」 ■リリースしました系 「PASTEL-ORBIT/TeamDyquemアプリ第19弾。ローグライク決定版「隣人は魔王」をリリースしました。」 「TeamDyquemアプリ第18段。ご当地バトルRTS「埼玉クエスト」をリリースしました。近隣の県を滅ぼそう(*-_-*) 埼玉以外でも遊べます #47app」 「アプリ新作「ネコりす マカロン」をリリースしました」 「埼玉県ご当地アプリ、「タッチ the さいたま」をリリースしました #47app」 「アプリ新作「ひよこガーデン」をリリースしました」 「TeamDyquem新作。結構真面目なアクションパズル「ネコりす」リリース」 「iPhoneアプリ作者が、iアプリ「泡リス女子部 for iアプリ」をリリースしました」 「自作iPhoneアプリ改良版、「ネコがゴミのようだネ:アーケード」をリリースしました」 「iPhoneアプリ作者が、「まりも育成」for iモードをリリースしました」 「iPhoneアプリ新作 「ナタ・デ・ネコ」 をリリースしました」 「秋刀魚は関係ないけれど、新作「i-Wishbone」リリース」 「アプリ新作「ネコがゴミのようだ」。プロモ動画をアップしてみた」 「「泡リス 女子部」、販売開始」 「AppBankにまりも紹介記事が!」 「ゲームプログラマとして参加。ご当地47都道府県アプリプロジェクト #47app」 □ビジネス系 「ゲームプログラマが語るドコモiPhoneと、インフラから合法的に大金を抜くスキーム」 「ゲームプログラマが語る。秀丸エディタのビジネスモデル」 ■SFネタ系 「ゲームプログラマがSFを語る。意識はどこからやってきて、死んで、そして何処へ行く?」 「ゲームプログラマが語る。気の遠くなるスキもない程の、宇宙の話」 「iPhoneアプリ作者が語る。流れ星に馳せる真実」 「iPhoneアプリ作者が警笛。どこでもドアの使い過ぎには注意」 「iPhoneアプリ作者が語るSETI理論。異星人さんは何処!?」 ![]() |
||