
2025.08.01
災害大国・日本に求められる“命しか守れない防災”からの脱却 最長2週間先の気象災害予測による対応策
浮動小数点数(全1記事)
リンクをコピー
記事をブックマーク
安原祐二氏(以下、安原):パート4です。大丈夫ですか。寝ていませんか? パート4を始めていきたいと思います。浮動小数点数、floatです。
簡単な問題を出してみましょう。float aに「1f」を入れた時に、Debug.Logでそのaを出力させたらConsoleに何が出ますか? 急に聞かれると困るかもしれませんが、これは引っかけ問題ではなくて「1」が出ます。
次ですね、「1/3」。1割る3を書いたら何になるかな。これはちょっと引っかけ問題かもしれないですね。「0」になります。これは大した話ではありませんが、1f割る3fと書けば0.333になりますが、1割る3だと切り捨てられちゃうよという、わりとどうでもいい話です。
次です。「3e-1f」と書いてあります。これ、わかりますか。これはもう知っているか知らないかだけなのですが、こういうふうに書いても、きちんとコンパイルは通るし理解されます。この答えは「0.3」です。ぜひこれはお家に帰ってやってみてもらいたいですね。
どういうことかというと、eというのが数字の後ろに急に出てきたら、その後ろの数が10のべき乗を掛けていることになるよ、という話です。これは覚えておいたほうがいいでしょうね。2や、ネイピア数ではなく、10です。
という話がありつつ、floatの話をしていきます。ちょっとゴチャゴチャした話になりますが、floatは32bitあって、中身はこうなっているんですね。これは調べるとネット上にいくらでもある情報ですが、符号が1bitあって、指数部が8bitあって、仮数部が23bitあります。
ざっくり言うと、仮数部に2の指数部乗を掛けたもののプラスマイナスが結果になります。
実はこれはちょっと嘘で、(スライドを示して)厳密に言うとこうですね。1.0をベースにしていて、指数部からは127を引いて掛けるというのが、規格上の決まりごとになっています。
なので今001111と書いてありますが、これは、この上の32bitでfloatにした時に、ちょうど1.0を表現できるビットパターンになっています。これはベテランプログラマーはわりと知っていますが、16進でいうと、3f800がfloatの1.0です。
ちょっと限界を探ってみましょう。まず指数部。指数部は規格上、マイナス126からプラス127までいけます。では、2の127がどのくらいの数字なのかと計算してみると、長い数字の後ろのほうにeと書いています。つまり、10の38乗を掛けている。
パート3で対数の話をした時に、だいたい3分の1と3倍の関係という話をしましたが、127の3分の1はだいたい38じゃないですか。これもだいたい合っているんですね。
けっこう大きな値ですね。小さいほうはどれくらいかというと、eのマイナス38乗、つまり10のマイナス38乗というすごく広い値です。
floatには限界があるということをなんとなく知っている方は多いと思います。ですが、実は表現の幅は超絶広いです。どのくらい広いかというと、これはちょっとお遊びで調べてみたのですが、10の36乗を表す、澗(かん)という単位があります。なので、100澗ぐらいの数字が限界になるわけです。この値まで使うことはあり得ないぐらいの大きな値を扱うことができます。
では、小さいほう。調べても調べても、10のマイナス24乗以下の単位が見つかりませんでした。誰か教えてほしいのですが、涅槃寂静(ねはんじゃくじょう)という尊い感じの単位があって、これでもまだ10のマイナス24乗です。なので、マイナス38乗どんだけだよというぐらい小さな値を表現できます。
また、一番下に小さく書きましたが、僕の知識の中で一番小さな物理定数を考えると、ディラック定数というものがあります。10のマイナス34乗なので、これでもぜんぜん大きいですね。
というぐらい小さな値を、実はfloatは表現できます。
ですが、やはり限界はあります。どこに限界があるかというと、むしろこの大きいほうのここです。23bitのほう。つまり大きな数字に小さな数字が足されている場合、表現できないということになります。
例えば(スライドの)下に書いてある、1,000万にすごく小さな値を足すことは、floatでは表現できません。
では、この23bitのほうをちょっと深掘りしてみましょう。この仮数部は、2のマイナス23乗という小さな値を扱えると主張していて、どのくらいの値なのか見てみると、このくらいになります。
1.0に足せる最小の数。floatのビットパターンの一番右側に1を立てて表示させるとこんなふうになります。このぐらいの値が限界ということになります。
1と、この小さな桁が始まるまでの距離は7桁ぐらいです。これも計算するとわりとわかるのですが、log10の2というのは0.3なので、23bitにこの数字を掛けると6.9という値が出てきます。なので、だいたい7桁というのが計算上もわかってくるわけです。
具体的にまずいところへ近づいていきましょうか。(スライドの)一番上ですね、10という数字に一番小さなbitを立てた時はこのぐらいです。100、1,000といって、10,000になった時に0.0009。これが一番小さな単位、解像度です。分解能と言いますが、そういう値になるわけです。
例えばUnityでトランスフォームに値を入れていたとしましょう。原点から10キロ離れたところでなにが起きているかというと、1ミリの分解能が限界になっているわけです。1ミリと1ミリの間、つまり0.5ミリみたいな値を表現できなくなっているということになります。10キロ離れるのはそんなにないかもしれませんが、これは知っておいたほうがよいでしょう。
もっとヤバいのは時間ですね。例えば1.0を1秒にするケースは多いと思いますが、そうすると24時間で86,400秒になるんですね。この状態でどのくらい小さな値が使えるのかというと、計算してみると7.8ミリぐらいが限界になります。
例えば、プログラム上で毎フレームdeltaTimeを足している部分があったとしましょう。24時間これを回していると、16ミリ秒足しているつもりでも分解能が7.8ミリになってしまうので、15ミリしか足されていないみたいな、おかしなことが起きてしまいます。これは明らかにおかしなことが起きるので、気をつけましょう。
実際ヤバいのは知っていても、具体的にどのくらいなのかというのは意外と知らない方が多いと思います。具体的に知っていると、嗅覚が働くというか、「これはヤバいんじゃない?」というのがわかってきます。
そういう問題にぶち当たってから調べるよりもやはり効率はよいので、このへんは知識として知っておくと制作に役立つかなと思います。
ちょっと実験です。原点からzの値をガンガンガンガン足してみました。まだけっこう大丈夫ですが、Standard Shaderで普通に出している男の子がだんだん、だんだん人の形を保てなくなっていくのがわかるでしょうか。
(会場笑)
900キロ離すとかはゲームではちょっとあり得ないと思いますが、ええーヤバい。ヤバい(笑)。ヤバいですね、これは本当にヤバいことがあります。
みなさん、こんなのやらないだろうと思うかもしれませんが、マップゲームとか考えてみてくださいよ。同じアプリで東京とロンドンの家を表現する時に、人によってはずーっと画面を見ていて、連続しているかもしれないですよね。その時にどう対応するのかみたいな、おもしろいですね。
もう人の形を保てなくなっていますが、マップゲームの場合だと、いろいろな対応はあると思いますが、例えば1キロなら1キロで原点に全体をずらすという処理がおそらく必要になるでしょう。
これはなんにも考えずにやった場合で、絶対こうなると考えるのは誤解があります。なので、ちょっとシェーダーを入れ替えます。右側の男の子は、がんばって姿勢を崩さないように僕がシェーダーを書いてみたものです。左側は先ほどと同じですね。
右側の男の子は崩れないのですが、結局シェーダーでがんばっても、アニメーションの部分の精度が落ちるので、首がガクガク動いたりして、結局駄目なのですね。こういう対応をしてもあまり意味はなくて、今は影を出していませんが、影を出すともっとヤバかったりします。ここをシェーダーでがんばる意味はほとんどないです。気をつけましょうという話になります。
おもしろいので、ぜひやってみてください。簡単にできます。トランスフォームのzの値を、ずっと足すだけです。
もう1つやり方があって、double(double precision floating point number)ですね。doubleを推奨したい。先ほど、時間の例がありましたね。86,400という数字があった時に、doubleだったらどうなるかというと、仮数部は52bitなので、24時間経っても0.014ナノ秒までいけます。かなり強力。365日ずーっとアプリを動かし続けても3.7ナノ秒までいけるので、doubleはほとんど無敵に近いですね。
もちろん、毎フレーム300足すとか、もっとヤバいケースがあるかもしれませんが、doubleにしておくと特に時間に関しては大丈夫です。
なので、僕はずっと足していくTimeとかをやる時は、だいたいdoubleを使うようにしています。doubleが遅いかというと、実は計算上はそんなに遅いわけではなくて、現代のプロセッサーだとぜんぜん遅くありません。むしろdoubleのほうが速いプロセッサーもあるぐらいなので、double使っていきましょう。
というわけでパート4が終わりました。floatの限界を具体的に知ってみようという、実験をやってみました。2進数と10進数の桁の関係がわかると、このへんの勘も働くでしょう。このあと公開しますが、ここについてもうちょっと詳しくブログを書いたので、興味ある方はぜひ見てください。というわけで、パート4は終わりです。
続きを読むには会員登録
(無料)が必要です。
会員登録していただくと、すべての記事が制限なく閲覧でき、
スピーカーフォローや記事のブックマークなど、便利な機能がご利用いただけます。
すでに会員の方はこちらからログイン
名刺アプリ「Eight」をご利用中の方は
こちらを読み込むだけで、すぐに記事が読めます!
スマホで読み込んで
ログインまたは登録作業をスキップ
2025.09.08
部下が不幸になる上司のNG行動5選 マネジメントは「自律と統制」のバランスでうまくいく
2025.09.10
人生の差は20代で決まる “指示待ち人間”で終わらないために積むべき4つの経験
2025.09.16
日本人が英語学習で苦戦する根本的原因 「言いたいことの順番」が真逆になる英語と日本語
2025.09.10
「やりたいこと」はないが「課題解決」自体を楽しめる人 Googleの「優秀なエンジニア」の定義
2025.09.04
「管理職になりたくない問題」の原因は上司にもある 部下の昇進意欲を削ぐ行動
2025.09.16
“できる仕事のキャパが10倍になった” 東証上場社長を変えた習慣「ピッパの法則」の効果
2025.09.11
自分の得意・不得意がわかるワーク 人生を再設計する「ライフキャリア」の見つけ方
2025.09.17
英語ネイティブは「would」をどう使っているか? 「Do you like〜」と「Would you like〜」の違い
2025.09.12
“起業が向いている人”と”経営が向いている人”は違う DMM亀山会長が語る、新規事業の生み出し方
2025.09.09
“指示待ち社員”から「自分で考え、動く社員」に育てる方法 セルフリーダーシップの発揮に重要な3つのアプローチ
管理職は罰ゲームではなかった!マネジメントスキル、リーダーシップは財産に!
2025.07.31 - 2025.07.31
後回しを断ち切り“すぐやる人”になる最速メソッド|東証上場社長実践の後回し撲滅法
2025.06.24 - 2025.06.24
「因数分解! 売れない理由は、“売り方”じゃなく “見方”にある」 ~マーケティング×ビジネス数学で、売上を動かす本質をつかむ~
2025.08.06 - 2025.08.06
【板挟みに苦しむ管理職へ】忙しさから“本当に抜け出す”唯一の方法
2025.07.09 - 2025.07.09
「英語OS」を身につけよ! −思考プロセスをアップデートし、英語学習の遠回りを終わらせよう!
2025.07.05 - 2025.07.05