[英]System.Windows.Media.Matrix does not use System.Double precision 64-bit number?
我試圖使用System.Windows.Media中的Matrix,但發現了一個我不了解的限制。
情況1 :
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
在第一種情況下,我們看到:一切似乎都很好!
情況2:
double m11 = 0.00000001, // 1E-08
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-16 <==> m11*m22-m12*m21 = 1E-08 * 1E-07 = 1E-15
if (mat.HasInverse) // false
mat.Invert(); // KO : System.InvalidOperationException: 'Transform is not invertible.'
但是在第二種情況下,我們可以看到(盡管矩陣檢查它是平方的並且其行列式不同於零),HasInverse為false,而Invert可能引發異常。 在這里,我可以看到的唯一區別是計算1E-15所需的精度。 但是Matrix似乎使用double和System.Double在64位精度應該使用:
值范圍從負1.79769313486232e308到正1.79769313486232e30
所以為什么 ? 感謝您提供的任何信息!
矩陣類使用雙精度型。 您可以在此處查看源代碼。
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
)
下面的代碼顯示“ Same results!”,表明您的計算與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
的實現,可以找到關於為什么沒有逆的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
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.