我尝试使用System.Windows.Media中的Matrix,但我找到了一个我不明白的限制。
案例1:
Array
(
[0] => Array
(
[allocation_date] => 2018-01-01
[t_project] => 10001
[t_assign_to] => G2E0357
[t_start_time] => 01:30 PM
[t_end_time] => 11:30 AM
)
[1] => Array
(
[allocation_date] => 2018-01-02
[t_project] => 10001
[t_assign_to] => G2E0357
[t_start_time] => 01:30 PM
[t_end_time] => 11:30 AM
)
[2] => Array
(
[allocation_date] => 2018-01-03
[t_project] => 10001
[t_assign_to] => G2E0357
[t_start_time] => 01:30 PM
[t_end_time] => 11:30 AM
)
)
在第一种情况下,我们看到:一切似乎都很好!
案例2:
double m11 = 0.0000001, // 1E-07
m12 = 0,
m21 = 0,
m22 = 0.0000001; // 1E-07
var mat = new Matrix(m11, m12, m21, m22, 0, 0);
var det = mat.Determinant; // det = 9.9999999999999988E-15 <==> m11*m22-m12*m21 = 1E-07 * 1E-07 = 1E-14
if (mat.HasInverse) // true
mat.Invert(); // OK
但是在第二种情况下我们可以看到(尽管矩阵检查它是正方形并且它的行列式与零不同)HasInverse为false并且Invert可能抛出异常。在这里,我能看到的唯一区别是计算1E-15期间所需的精度。但是Matrix似乎使用了double和64位的System.Double精度应该使用:
值从负1.79769313486232e308到正数 1.79769313486232e30
为什么?感谢任何可能有帮助的消息!
答案 0 :(得分:0)
矩阵类DOES使用双精度数。 You can check the source code here.
public double Determinant
{
get
{
switch (_type)
{
case MatrixTypes.TRANSFORM_IS_IDENTITY:
case MatrixTypes.TRANSFORM_IS_TRANSLATION:
return 1.0;
case MatrixTypes.TRANSFORM_IS_SCALING:
case MatrixTypes.TRANSFORM_IS_SCALING | MatrixTypes.TRANSFORM_IS_TRANSLATION:
return(_m11 * _m22);
default:
return(_m11 * _m22) - (_m12 * _m21);
}
}
}
(其中_m11等都是double
)
以下代码打印“相同结果!”,表示您的计算与Matrix.Determinant
之间没有区别:
using System;
namespace Demo
{
class Program
{
static void Main()
{
double m11 = 0.00000001, // 1E-08
m12 = 0,
m21 = 0,
m22 = 0.0000001; // 1E-07
double det = m11 * m22 - m12 * m21;
Console.WriteLine(det);
var mat = new System.Windows.Media.Matrix(m11, m12, m21, m22, 0, 0);
Console.WriteLine(mat.Determinant);
if (mat.Determinant == det)
Console.WriteLine("Same results!"); // This is printed.
Console.WriteLine(mat.HasInverse); // Has no inverse, though.
}
}
}
通过查看HasInverse
的实现,可以找到关于为何说没有逆的答案:
public bool HasInverse
{
get
{
return !DoubleUtil.IsZero(Determinant);
}
}
这里实施了DoubleUtil.IsZero()
(我简化了这一点,以便更明显地发生了什么):
public static bool IsZero(double value)
{
return Math.Abs(value) < 2.22044604925031E-15;
}
在这种情况下,value
1E-15
小于2.22044604925031E-15
,因此DoubleUtil.IsZero()
返回true
,因此Matrix.HasInverse
返回false
}}