In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: flash on 2010-11-4

行列式に逆行列が存在するかどうかは 行列式 != 0
で見ていると思います。
数学的には回転行列の行列式は1、あるいは全ての回転に対して逆回転が定義できて
それから回転行列を作ることができるから、逆行列は存在します。

コンピュータは不動点小数演算をしますので、
A * A^-1 = 1
の成分計算をチェックして、計算間違ってるじゃんってのは
少しかわいそうだと思います。

勿論、誤差が全く出ないような代数的な演算を実行するような数学的なクラスとかも
実装できますが、実用上は(速度も遅いし)必要ないと思います。

不動点小数演算における誤差の評価とか、コンピュータ・サイエンスの大事な一分野ですが、
さすがにやりたくないので、お手軽に誤差の最大値を求めてみました。1e-7のオーダーでした。
ちなみにこれは、地球の直径約13000kmに対して、
13000 * 1000 * 1e-7 = 1.3 [m]という誤差ですね。
Get Adobe Flash player
by 9re 05 Nov 2010
    Embed
/**
 * Copyright 9re ( http://wonderfl.net/user/9re )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/FwxV
 */

/*
行列式に逆行列が存在するかどうかは 行列式 != 0
で見ていると思います。
数学的には回転行列の行列式は1、あるいは全ての回転に対して逆回転が定義できて
それから回転行列を作ることができるから、逆行列は存在します。

コンピュータは不動点小数演算をしますので、
A * A^-1 = 1
の成分計算をチェックして、計算間違ってるじゃんってのは
少しかわいそうだと思います。

勿論、誤差が全く出ないような代数的な演算を実行するような数学的なクラスとかも
実装できますが、実用上は(速度も遅いし)必要ないと思います。

不動点小数演算における誤差の評価とか、コンピュータ・サイエンスの大事な一分野ですが、
さすがにやりたくないので、お手軽に誤差の最大値を求めてみました。1e-7のオーダーでした。
ちなみにこれは、地球の直径約13000kmに対して、
13000 * 1000 * 1e-7 = 1.3 [m]という誤差ですね。
*/
package
{
    import flash.display.Sprite;
    import flash.geom.Matrix3D;
    import flash.geom.Vector3D;
    import flash.text.TextField;
    
    public class InvertMatrix_test extends Sprite
    {
        public function InvertMatrix_test()
        {
            var t:TextField = addChild( new TextField() ) as TextField;
            t.width = t.height = 465;
            
            var m:Matrix3D = new Matrix3D();
            var identityVector:Vector.<Number> = m.rawData;
            var inv:Matrix3D = new Matrix3D();
            var v:Vector.<Number>;
            
            var notInvCount:int = 0;
            var count:int = 0;
            
            var str:String = "";
            var maxDiff:Number = Number.NEGATIVE_INFINITY;            
            
            for(var rot:int = 0; rot<360; rot++){
                m.rawData = identityVector;
                m.appendRotation( rot, Vector3D.X_AXIS );
                inv.rawData = m.rawData;
                if( inv.invert() )
                {
                    m.append( inv );
                    
                    v = m.rawData;
                    for(var i:int = 0; i<16; i++)
                    {
                        var a:Number = identityVector[i];
                        var b:Number = v[i];
                        if(a != b){
                            maxDiff = Math.max(Math.abs(a - b), maxDiff);
                            str += "rot = " + rot + " 判定箇所 = " + i + "  mat = " + v.toString() + "\n";
                            count++;
                            break;
                        }
                    }
                }else notInvCount++;
            }
            
            var str2:String = "(FPが認識する)invert失敗 :: " + notInvCount + "\n";
            str2 += "(成功と言ってるけど)invert失敗 :: " + count + "\n\n";
            str2 += "誤差の最大値: " + maxDiff + "\n";
            str2 += "失敗した行列\n\n";
            str2 += str;
            
            t.text = str2;
        }
    }
}