閉じる

GDLで「実数タイプを使用すると精度に問題が生じる可能性があります」というメッセージが出てくる場合の対処法

GDLモデラーの皆さんこんにちは。

GDLオブジェクトの作成中、「スクリプトを確認」ボタンを押すと下のようなメッセージが出てきてしまうことがあると思います。

特に気にせず「継続」を押しても普通に問題なく動くぞ?何ぞこれ?という方に、エラーメッセージを出さない書き方と多分こういうことですよという解説をします。

※筆者はプログラマでも何でも無いので解説に勘違いが含まれている場合がありますが、対処法は概ね合っているはずです。
※GDLの基礎的な知識がある前提で書いていますので、細かい解説はしていません。

エラーが出る例

例えばこのようにコードを書くとエラーが表示されると思います。

<パラメータ>

<3Dスクリプト>

if XXX = 1 then
  brick 1,1,1
endif

XXXのパラメータが 1mぴったりのときに1m x 1m x 1mの立方体が表示するスクリプトです。エラーが出ます。

対処法

対処は簡単です。以下のように追記・修正します。

<マスタスクリプト>

EPS = 0.00001

<3Dスクリプト>

if abs(XXX - 1) < EPS then
brick 1,1,1
endif

動作そのものは全く変わっていませんが、書き換えてから「スクリプトを確認」ボタンを押すと問題が解決されています。

0mのときに立方体を表示する場合は abs(XXX) < EPS , 2mのときはabs(XXX) < EPS です。

解説

どのようなことが起きているのでしょうか。
まずは変更したスクリプトの動作について解説します。

変更前のスクリプトは「変数XXXが1(m)のときに立方体を表示する」
変更後のスクリプトは「変数XXX – 1の絶対値が0.00001未満のときに立方体を表示する」
という動作をしています。

変更前がぴったり1mのときにしか動作しないのに対し、変更後は0.99999m ~ 1.00001mまで±0.00001mの誤差まで動作します。

この誤差がポイントです。

ところでGDLの変数には「実数」「整数」「材質」などのタイプ(型)があります。

「整数」は-2,-1,0,1,2…など小数を持ちません。
「実数」は-2.93892など小数値を保持できます。
「長さ」も実数同様に小数値を表現できる型です。
GDLでは小数を「浮動小数点」という方式で扱っています。(他のプログラミング言語でも一般的な方式です)

この浮動小数点は大きな桁数の小数を扱えるのと引き換えに、わずかな誤差が生じます。
なんで!?コンピュータなんだから誤差なんかないでしょ?と思いますよね?私も思います。でもそういうものなんです。飲み込んで下さい。
気になる人は「浮動小数点 誤差」でググって下さい。

つまり、この誤差のせいでArchicadの入力・表示上1mだったとしても、コンピュータの内部的に1.0000000001mだったり0.999999999999mだったりします。

普通に扱っている分には問題にならない0.01mm以下の誤差ですが、条件式として等値(=)で扱う場合は、この誤差のせいで「同じ値」として判定されない場合があります。
1.0000000000m と 1.00000000001mはイコールじゃないですよね。

その誤差を、十分小さい値(EPS = 0.00001)の範囲で吸収している、という理屈です。もう一度変更後のスクリプトを見ると誤差を吸収しているのがわかると思います。
(ちなみにEPSという変数名は数学で非常に小さい数値を表すことが多い「ε」から来ているそうです)

ということで、if文やfor文などの条件式の変数に「整数」以外の型を使う場合は気をつけましょう、という話です。

一見正常に動いていても、条件によっては意図しない動きをしてしまいますので、エラーは無視せずしっかりと対処するべきかと思います。


記事をシェア!

About kotetsu

コメントを残す

2019 © GRAPHISOFT JAPAN